diff options
102 files changed, 807 insertions, 590 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt index f9753c416974..b24583aa34c3 100644 --- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt @@ -14,11 +14,6 @@ Required properies: - #size-cells : The value of this property must be 1 - ranges : defines mapping between pin controller node (parent) to gpio-bank node (children). - - interrupt-parent: phandle of the interrupt parent to which the external - GPIO interrupts are forwarded to. - - st,syscfg: Should be phandle/offset pair. The phandle to the syscon node - which includes IRQ mux selection register, and the offset of the IRQ mux - selection register. - pins-are-numbered: Specify the subnodes are using numbered pinmux to specify pins. @@ -37,6 +32,11 @@ Required properties: Optional properties: - reset: : Reference to the reset controller + - interrupt-parent: phandle of the interrupt parent to which the external + GPIO interrupts are forwarded to. + - st,syscfg: Should be phandle/offset pair. The phandle to the syscon node + which includes IRQ mux selection register, and the offset of the IRQ mux + selection register. Example: #include <dt-bindings/pinctrl/stm32f429-pinfunc.h> diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 14cdc101d165..1b5f15653b1b 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -447,7 +447,6 @@ prototypes: int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t start, loff_t end, int datasync); - int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index d619c8d71966..b5039a00caaf 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -828,7 +828,6 @@ struct file_operations { int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); - int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); @@ -370,7 +370,7 @@ LDFLAGS_MODULE = CFLAGS_KERNEL = AFLAGS_KERNEL = LDFLAGS_vmlinux = -CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im +CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im -Wno-maybe-uninitialized CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,) @@ -620,7 +620,6 @@ ARCH_CFLAGS := include arch/$(SRCARCH)/Makefile KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,) -KBUILD_CFLAGS += $(call cc-disable-warning,maybe-uninitialized,) KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION @@ -629,15 +628,18 @@ KBUILD_CFLAGS += $(call cc-option,-fdata-sections,) endif ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -KBUILD_CFLAGS += -Os +KBUILD_CFLAGS += -Os $(call cc-disable-warning,maybe-uninitialized,) else ifdef CONFIG_PROFILE_ALL_BRANCHES -KBUILD_CFLAGS += -O2 +KBUILD_CFLAGS += -O2 $(call cc-disable-warning,maybe-uninitialized,) else KBUILD_CFLAGS += -O2 endif endif +KBUILD_CFLAGS += $(call cc-ifversion, -lt, 0409, \ + $(call cc-disable-warning,maybe-uninitialized,)) + # Tell gcc to never replace conditional load with a non-conditional one KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0) diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 864adad52280..25f81a1db9f9 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -68,7 +68,9 @@ cflags-$(CONFIG_ARC_DW2_UNWIND) += -fasynchronous-unwind-tables $(cfi) ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE # Generic build system uses -O2, we want -O3 # Note: No need to add to cflags-y as that happens anyways -ARCH_CFLAGS += -O3 +# +# Disable the false maybe-uninitialized warings gcc spits out at -O3 +ARCH_CFLAGS += -O3 $(call cc-disable-warning,maybe-uninitialized,) endif # small data is default for elf32 tool-chain. If not usable, disable it diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 39feb85a6931..6e1cb8c5af4d 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -1,7 +1,7 @@ #ifndef __ASM_ALTERNATIVE_H #define __ASM_ALTERNATIVE_H -#include <asm/cpufeature.h> +#include <asm/cpucaps.h> #include <asm/insn.h> #ifndef __ASSEMBLY__ diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h new file mode 100644 index 000000000000..87b446535185 --- /dev/null +++ b/arch/arm64/include/asm/cpucaps.h @@ -0,0 +1,40 @@ +/* + * arch/arm64/include/asm/cpucaps.h + * + * Copyright (C) 2016 ARM Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef __ASM_CPUCAPS_H +#define __ASM_CPUCAPS_H + +#define ARM64_WORKAROUND_CLEAN_CACHE 0 +#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 +#define ARM64_WORKAROUND_845719 2 +#define ARM64_HAS_SYSREG_GIC_CPUIF 3 +#define ARM64_HAS_PAN 4 +#define ARM64_HAS_LSE_ATOMICS 5 +#define ARM64_WORKAROUND_CAVIUM_23154 6 +#define ARM64_WORKAROUND_834220 7 +#define ARM64_HAS_NO_HW_PREFETCH 8 +#define ARM64_HAS_UAO 9 +#define ARM64_ALT_PAN_NOT_UAO 10 +#define ARM64_HAS_VIRT_HOST_EXTN 11 +#define ARM64_WORKAROUND_CAVIUM_27456 12 +#define ARM64_HAS_32BIT_EL0 13 +#define ARM64_HYP_OFFSET_LOW 14 +#define ARM64_MISMATCHED_CACHE_LINE_SIZE 15 + +#define ARM64_NCAPS 16 + +#endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index a27c3245ba21..0bc0b1de90c4 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -11,6 +11,7 @@ #include <linux/jump_label.h> +#include <asm/cpucaps.h> #include <asm/hwcap.h> #include <asm/sysreg.h> @@ -24,25 +25,6 @@ #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) #define cpu_feature(x) ilog2(HWCAP_ ## x) -#define ARM64_WORKAROUND_CLEAN_CACHE 0 -#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 -#define ARM64_WORKAROUND_845719 2 -#define ARM64_HAS_SYSREG_GIC_CPUIF 3 -#define ARM64_HAS_PAN 4 -#define ARM64_HAS_LSE_ATOMICS 5 -#define ARM64_WORKAROUND_CAVIUM_23154 6 -#define ARM64_WORKAROUND_834220 7 -#define ARM64_HAS_NO_HW_PREFETCH 8 -#define ARM64_HAS_UAO 9 -#define ARM64_ALT_PAN_NOT_UAO 10 -#define ARM64_HAS_VIRT_HOST_EXTN 11 -#define ARM64_WORKAROUND_CAVIUM_27456 12 -#define ARM64_HAS_32BIT_EL0 13 -#define ARM64_HYP_OFFSET_LOW 14 -#define ARM64_MISMATCHED_CACHE_LINE_SIZE 15 - -#define ARM64_NCAPS 16 - #ifndef __ASSEMBLY__ #include <linux/kernel.h> diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h index 23acc00be32d..fc756e22c84c 100644 --- a/arch/arm64/include/asm/lse.h +++ b/arch/arm64/include/asm/lse.h @@ -5,7 +5,6 @@ #include <linux/stringify.h> #include <asm/alternative.h> -#include <asm/cpufeature.h> #ifdef __ASSEMBLER__ diff --git a/arch/nios2/kernel/time.c b/arch/nios2/kernel/time.c index d9563ddb337e..746bf5caaffc 100644 --- a/arch/nios2/kernel/time.c +++ b/arch/nios2/kernel/time.c @@ -324,6 +324,7 @@ static int __init nios2_time_init(struct device_node *timer) ret = nios2_clocksource_init(timer); break; default: + ret = 0; break; } diff --git a/arch/openrisc/include/asm/cache.h b/arch/openrisc/include/asm/cache.h index 4ce7a01a252d..5f55da9cbfd5 100644 --- a/arch/openrisc/include/asm/cache.h +++ b/arch/openrisc/include/asm/cache.h @@ -23,6 +23,8 @@ * they shouldn't be hard-coded! */ +#define __ro_after_init __read_mostly + #define L1_CACHE_BYTES 16 #define L1_CACHE_SHIFT 4 diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index 28f03ca60100..794bebb43d23 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -363,11 +363,11 @@ out: static int diag224_get_name_table(void) { /* memory must be below 2GB */ - diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); + diag224_cpu_names = (char *) __get_free_page(GFP_KERNEL | GFP_DMA); if (!diag224_cpu_names) return -ENOMEM; if (diag224(diag224_cpu_names)) { - kfree(diag224_cpu_names); + free_page((unsigned long) diag224_cpu_names); return -EOPNOTSUPP; } EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16); @@ -376,7 +376,7 @@ static int diag224_get_name_table(void) static void diag224_delete_name_table(void) { - kfree(diag224_cpu_names); + free_page((unsigned long) diag224_cpu_names); } static int diag224_idx2name(int index, char *name) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 000e6e91f6a0..3667d20e997f 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -62,9 +62,11 @@ SECTIONS . = ALIGN(PAGE_SIZE); __start_ro_after_init = .; + __start_data_ro_after_init = .; .data..ro_after_init : { *(.data..ro_after_init) } + __end_data_ro_after_init = .; EXCEPTION_TABLE(16) . = ALIGN(PAGE_SIZE); __end_ro_after_init = .; diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 7350c8bc13a2..6b2f72f523b9 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -423,7 +423,7 @@ static int __s390_dma_map_sg(struct device *dev, struct scatterlist *sg, dma_addr_t dma_addr_base, dma_addr; int flags = ZPCI_PTE_VALID; struct scatterlist *s; - unsigned long pa; + unsigned long pa = 0; int ret; size = PAGE_ALIGN(size); diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 0ab5ee1c26af..aa8b0672f87a 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -888,7 +888,7 @@ static int helper_rfc4106_encrypt(struct aead_request *req) unsigned long auth_tag_len = crypto_aead_authsize(tfm); u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN))); struct scatter_walk src_sg_walk; - struct scatter_walk dst_sg_walk; + struct scatter_walk dst_sg_walk = {}; unsigned int i; /* Assuming we are supporting rfc4106 64-bit extended */ @@ -968,7 +968,7 @@ static int helper_rfc4106_decrypt(struct aead_request *req) u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN))); u8 authTag[16]; struct scatter_walk src_sg_walk; - struct scatter_walk dst_sg_walk; + struct scatter_walk dst_sg_walk = {}; unsigned int i; if (unlikely(req->assoclen != 16 && req->assoclen != 20)) diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index c7364bd633e1..51287cd90bf6 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -1042,8 +1042,11 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life) if (apm_info.get_power_status_broken) return APM_32_UNSUPPORTED; - if (apm_bios_call(&call)) + if (apm_bios_call(&call)) { + if (!call.err) + return APM_NO_ERROR; return call.err; + } *status = call.ebx; *bat = call.ecx; if (apm_info.get_power_status_swabinminutes) { diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6cfb5cacc253..575aa65436d1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -179,6 +179,7 @@ #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 #define USB_DEVICE_ID_ATEN_CS682 0x2213 +#define USB_DEVICE_ID_ATEN_CS692 0x8021 #define USB_VENDOR_ID_ATMEL 0x03eb #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c index 5614fee82347..3a84aaf1418b 100644 --- a/drivers/hid/hid-sensor-custom.c +++ b/drivers/hid/hid-sensor-custom.c @@ -292,11 +292,11 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr, bool input = false; int value = 0; - if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage, + if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage, name) == 3) { feature = true; field_index = index + sensor_inst->input_field_count; - } else if (sscanf(attr->attr.name, "input-%d-%x-%s", &index, &usage, + } else if (sscanf(attr->attr.name, "input-%x-%x-%s", &index, &usage, name) == 3) { input = true; field_index = index; @@ -398,7 +398,7 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr, char name[HID_CUSTOM_NAME_LENGTH]; int value; - if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage, + if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage, name) == 3) { field_index = index + sensor_inst->input_field_count; } else diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 658a607dc6d9..c5c3d6111729 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -251,6 +251,9 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); int report_size; int ret = 0; + u8 *val_ptr; + int buffer_index = 0; + int i; mutex_lock(&data->mutex); report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); @@ -271,7 +274,17 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, goto done_proc; } ret = min(report_size, buffer_size); - memcpy(buffer, report->field[field_index]->value, ret); + + val_ptr = (u8 *)report->field[field_index]->value; + for (i = 0; i < report->field[field_index]->report_count; ++i) { + if (buffer_index >= ret) + break; + + memcpy(&((u8 *)buffer)[buffer_index], val_ptr, + report->field[field_index]->report_size / 8); + val_ptr += sizeof(__s32); + buffer_index += (report->field[field_index]->report_size / 8); + } done_proc: mutex_unlock(&data->mutex); diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index e2517c11e0ee..0c9ac4d5d850 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -638,6 +638,58 @@ eoi: } /** + * ish_disable_dma() - disable dma communication between host and ISHFW + * @dev: ishtp device pointer + * + * Clear the dma enable bit and wait for dma inactive. + * + * Return: 0 for success else error code. + */ +static int ish_disable_dma(struct ishtp_device *dev) +{ + unsigned int dma_delay; + + /* Clear the dma enable bit */ + ish_reg_write(dev, IPC_REG_ISH_RMP2, 0); + + /* wait for dma inactive */ + for (dma_delay = 0; dma_delay < MAX_DMA_DELAY && + _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA); + dma_delay += 5) + mdelay(5); + + if (dma_delay >= MAX_DMA_DELAY) { + dev_err(dev->devc, + "Wait for DMA inactive timeout\n"); + return -EBUSY; + } + + return 0; +} + +/** + * ish_wakeup() - wakeup ishfw from waiting-for-host state + * @dev: ishtp device pointer + * + * Set the dma enable bit and send a void message to FW, + * it wil wakeup FW from waiting-for-host state. + */ +static void ish_wakeup(struct ishtp_device *dev) +{ + /* Set dma enable bit */ + ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); + + /* + * Send 0 IPC message so that ISH FW wakes up if it was already + * asleep. + */ + ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); + + /* Flush writes to doorbell and REMAP2 */ + ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); +} + +/** * _ish_hw_reset() - HW reset * @dev: ishtp device pointer * @@ -649,7 +701,6 @@ static int _ish_hw_reset(struct ishtp_device *dev) { struct pci_dev *pdev = dev->pdev; int rv; - unsigned int dma_delay; uint16_t csr; if (!pdev) @@ -664,15 +715,8 @@ static int _ish_hw_reset(struct ishtp_device *dev) return -EINVAL; } - /* Now trigger reset to FW */ - ish_reg_write(dev, IPC_REG_ISH_RMP2, 0); - - for (dma_delay = 0; dma_delay < MAX_DMA_DELAY && - _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA); - dma_delay += 5) - mdelay(5); - - if (dma_delay >= MAX_DMA_DELAY) { + /* Disable dma communication between FW and host */ + if (ish_disable_dma(dev)) { dev_err(&pdev->dev, "Can't reset - stuck with DMA in-progress\n"); return -EBUSY; @@ -690,16 +734,8 @@ static int _ish_hw_reset(struct ishtp_device *dev) csr |= PCI_D0; pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); - ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); - - /* - * Send 0 IPC message so that ISH FW wakes up if it was already - * asleep - */ - ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); - - /* Flush writes to doorbell and REMAP2 */ - ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); + /* Now we can enable ISH DMA operation and wakeup ISHFW */ + ish_wakeup(dev); return 0; } @@ -758,16 +794,9 @@ static int _ish_ipc_reset(struct ishtp_device *dev) int ish_hw_start(struct ishtp_device *dev) { ish_set_host_rdy(dev); - /* After that we can enable ISH DMA operation */ - ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); - /* - * Send 0 IPC message so that ISH FW wakes up if it was already - * asleep - */ - ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); - /* Flush write to doorbell */ - ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); + /* After that we can enable ISH DMA operation and wakeup ISHFW */ + ish_wakeup(dev); set_host_ready(dev); @@ -876,6 +905,21 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) */ void ish_device_disable(struct ishtp_device *dev) { + struct pci_dev *pdev = dev->pdev; + + if (!pdev) + return; + + /* Disable dma communication between FW and host */ + if (ish_disable_dma(dev)) { + dev_err(&pdev->dev, + "Can't reset - stuck with DMA in-progress\n"); + return; + } + + /* Put ISH to D3hot state for power saving */ + pci_set_power_state(pdev, PCI_D3hot); + dev->dev_state = ISHTP_DEV_DISABLED; ish_clr_host_rdy(dev); } diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index 42f0beeb09fd..20d647d2dd2c 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -146,7 +146,7 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; /* request and enable interrupt */ - ret = request_irq(pdev->irq, ish_irq_handler, IRQF_NO_SUSPEND, + ret = request_irq(pdev->irq, ish_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) { dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n", @@ -202,6 +202,7 @@ static void ish_remove(struct pci_dev *pdev) kfree(ishtp_dev); } +#ifdef CONFIG_PM static struct device *ish_resume_device; /** @@ -293,7 +294,6 @@ static int ish_resume(struct device *device) return 0; } -#ifdef CONFIG_PM static const struct dev_pm_ops ish_pm_ops = { .suspend = ish_suspend, .resume = ish_resume, @@ -301,7 +301,7 @@ static const struct dev_pm_ops ish_pm_ops = { #define ISHTP_ISH_PM_OPS (&ish_pm_ops) #else #define ISHTP_ISH_PM_OPS NULL -#endif +#endif /* CONFIG_PM */ static struct pci_driver ish_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 354d49ea36dd..e6cfd323babc 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -63,6 +63,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index adae6848ffb2..a74c075a30ec 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -536,8 +536,10 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, hwdev->groups = devm_kcalloc(dev, ngroups, sizeof(*groups), GFP_KERNEL); - if (!hwdev->groups) - return ERR_PTR(-ENOMEM); + if (!hwdev->groups) { + err = -ENOMEM; + goto free_hwmon; + } attrs = __hwmon_create_attrs(dev, drvdata, chip); if (IS_ERR(attrs)) { diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 36bf50ebb187..89a6b0546804 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1094,47 +1094,47 @@ static void cma_save_ib_info(struct sockaddr *src_addr, } } -static void cma_save_ip4_info(struct sockaddr *src_addr, - struct sockaddr *dst_addr, +static void cma_save_ip4_info(struct sockaddr_in *src_addr, + struct sockaddr_in *dst_addr, struct cma_hdr *hdr, __be16 local_port) { - struct sockaddr_in *ip4; - if (src_addr) { - ip4 = (struct sockaddr_in *)src_addr; - ip4->sin_family = AF_INET; - ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr; - ip4->sin_port = local_port; + *src_addr = (struct sockaddr_in) { + .sin_family = AF_INET, + .sin_addr.s_addr = hdr->dst_addr.ip4.addr, + .sin_port = local_port, + }; } if (dst_addr) { - ip4 = (struct sockaddr_in *)dst_addr; - ip4->sin_family = AF_INET; - ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr; - ip4->sin_port = hdr->port; + *dst_addr = (struct sockaddr_in) { + .sin_family = AF_INET, + .sin_addr.s_addr = hdr->src_addr.ip4.addr, + .sin_port = hdr->port, + }; } } -static void cma_save_ip6_info(struct sockaddr *src_addr, - struct sockaddr *dst_addr, +static void cma_save_ip6_info(struct sockaddr_in6 *src_addr, + struct sockaddr_in6 *dst_addr, struct cma_hdr *hdr, __be16 local_port) { - struct sockaddr_in6 *ip6; - if (src_addr) { - ip6 = (struct sockaddr_in6 *)src_addr; - ip6->sin6_family = AF_INET6; - ip6->sin6_addr = hdr->dst_addr.ip6; - ip6->sin6_port = local_port; + *src_addr = (struct sockaddr_in6) { + .sin6_family = AF_INET6, + .sin6_addr = hdr->dst_addr.ip6, + .sin6_port = local_port, + }; } if (dst_addr) { - ip6 = (struct sockaddr_in6 *)dst_addr; - ip6->sin6_family = AF_INET6; - ip6->sin6_addr = hdr->src_addr.ip6; - ip6->sin6_port = hdr->port; + *dst_addr = (struct sockaddr_in6) { + .sin6_family = AF_INET6, + .sin6_addr = hdr->src_addr.ip6, + .sin6_port = hdr->port, + }; } } @@ -1159,10 +1159,12 @@ static int cma_save_ip_info(struct sockaddr *src_addr, switch (cma_get_ip_ver(hdr)) { case 4: - cma_save_ip4_info(src_addr, dst_addr, hdr, port); + cma_save_ip4_info((struct sockaddr_in *)src_addr, + (struct sockaddr_in *)dst_addr, hdr, port); break; case 6: - cma_save_ip6_info(src_addr, dst_addr, hdr, port); + cma_save_ip6_info((struct sockaddr_in6 *)src_addr, + (struct sockaddr_in6 *)dst_addr, hdr, port); break; default: return -EAFNOSUPPORT; diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 15c01c3cd540..e6f9b2d745ca 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2636,17 +2636,26 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) /* And we're up. Go go go! */ of_iommu_set_ops(dev->of_node, &arm_smmu_ops); #ifdef CONFIG_PCI - pci_request_acs(); - ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops); - if (ret) - return ret; + if (pci_bus_type.iommu_ops != &arm_smmu_ops) { + pci_request_acs(); + ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops); + if (ret) + return ret; + } #endif #ifdef CONFIG_ARM_AMBA - ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops); - if (ret) - return ret; + if (amba_bustype.iommu_ops != &arm_smmu_ops) { + ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops); + if (ret) + return ret; + } #endif - return bus_set_iommu(&platform_bus_type, &arm_smmu_ops); + if (platform_bus_type.iommu_ops != &arm_smmu_ops) { + ret = bus_set_iommu(&platform_bus_type, &arm_smmu_ops); + if (ret) + return ret; + } + return 0; } static int arm_smmu_device_remove(struct platform_device *pdev) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c841eb7a1a74..8f7281444551 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -324,8 +324,10 @@ struct arm_smmu_master_cfg { #define INVALID_SMENDX -1 #define __fwspec_cfg(fw) ((struct arm_smmu_master_cfg *)fw->iommu_priv) #define fwspec_smmu(fw) (__fwspec_cfg(fw)->smmu) +#define fwspec_smendx(fw, i) \ + (i >= fw->num_ids ? INVALID_SMENDX : __fwspec_cfg(fw)->smendx[i]) #define for_each_cfg_sme(fw, i, idx) \ - for (i = 0; idx = __fwspec_cfg(fw)->smendx[i], i < fw->num_ids; ++i) + for (i = 0; idx = fwspec_smendx(fw, i), i < fw->num_ids; ++i) struct arm_smmu_device { struct device *dev; @@ -1228,6 +1230,16 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENXIO; } + /* + * FIXME: The arch/arm DMA API code tries to attach devices to its own + * domains between of_xlate() and add_device() - we have no way to cope + * with that, so until ARM gets converted to rely on groups and default + * domains, just say no (but more politely than by dereferencing NULL). + * This should be at least a WARN_ON once that's sorted. + */ + if (!fwspec->iommu_priv) + return -ENODEV; + smmu = fwspec_smmu(fwspec); /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); @@ -1390,7 +1402,7 @@ static int arm_smmu_add_device(struct device *dev) fwspec = dev->iommu_fwspec; if (ret) goto out_free; - } else if (fwspec) { + } else if (fwspec && fwspec->ops == &arm_smmu_ops) { smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode)); } else { return -ENODEV; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a4407eabf0e6..3965e73db51c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1711,6 +1711,7 @@ static void disable_dmar_iommu(struct intel_iommu *iommu) if (!iommu->domains || !iommu->domain_ids) return; +again: spin_lock_irqsave(&device_domain_lock, flags); list_for_each_entry_safe(info, tmp, &device_domain_list, global) { struct dmar_domain *domain; @@ -1723,10 +1724,19 @@ static void disable_dmar_iommu(struct intel_iommu *iommu) domain = info->domain; - dmar_remove_one_dev_info(domain, info->dev); + __dmar_remove_one_dev_info(info); - if (!domain_type_is_vm_or_si(domain)) + if (!domain_type_is_vm_or_si(domain)) { + /* + * The domain_exit() function can't be called under + * device_domain_lock, as it takes this lock itself. + * So release the lock here and re-run the loop + * afterwards. + */ + spin_unlock_irqrestore(&device_domain_lock, flags); domain_exit(domain); + goto again; + } } spin_unlock_irqrestore(&device_domain_lock, flags); diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index f95a6bc839d5..cede3975d04b 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -118,7 +118,7 @@ static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol, *protocol = RC_TYPE_RC6_MCE; dev &= 0x7f; dprintk(1, "ir hauppauge (rc6-mce): t%d vendor=%d dev=%d code=%d\n", - toggle, vendor, dev, code); + *ptoggle, vendor, dev, code); } else { *ptoggle = 0; *protocol = RC_TYPE_RC6_6A_32; diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 92d5408684ac..47ce9d5de4c6 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -704,7 +704,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) struct dvb_usb_device *d = purb->context; struct dib0700_rc_response *poll_reply; enum rc_type protocol; - u32 uninitialized_var(keycode); + u32 keycode; u8 toggle; deb_info("%s()\n", __func__); @@ -745,7 +745,8 @@ static void dib0700_rc_urb_completion(struct urb *purb) poll_reply->nec.data == 0x00 && poll_reply->nec.not_data == 0xff) { poll_reply->data_state = 2; - break; + rc_repeat(d->rc_dev); + goto resubmit; } if ((poll_reply->nec.data ^ poll_reply->nec.not_data) != 0xff) { diff --git a/drivers/of/base.c b/drivers/of/base.c index d687e6de24a0..a0bccb54a9bd 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2077,8 +2077,6 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) name = of_get_property(of_aliases, "stdout", NULL); if (name) of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); - if (of_stdout) - console_set_by_of(); } if (!of_aliases) diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 153f3122283d..b6b316de055c 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -107,7 +107,7 @@ int soc_pcmcia_regulator_set(struct soc_pcmcia_socket *skt, ret = regulator_enable(r->reg); } else { - regulator_disable(r->reg); + ret = regulator_disable(r->reg); } if (ret == 0) r->on = on; diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c index c8c72e8259d3..87b46390b695 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c @@ -26,7 +26,7 @@ #define ASPEED_G5_NR_PINS 228 -#define COND1 SIG_DESC_BIT(SCU90, 6, 0) +#define COND1 { SCU90, BIT(6), 0, 0 } #define COND2 { SCU94, GENMASK(1, 0), 0, 0 } #define B14 0 diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index 7f7700716398..5d1e505c3c63 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -844,6 +844,6 @@ static struct platform_driver iproc_gpio_driver = { static int __init iproc_gpio_init(void) { - return platform_driver_probe(&iproc_gpio_driver, iproc_gpio_probe); + return platform_driver_register(&iproc_gpio_driver); } arch_initcall_sync(iproc_gpio_init); diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c index 35783db1c10b..c8deb8be1da7 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c @@ -741,6 +741,6 @@ static struct platform_driver nsp_gpio_driver = { static int __init nsp_gpio_init(void) { - return platform_driver_probe(&nsp_gpio_driver, nsp_gpio_probe); + return platform_driver_register(&nsp_gpio_driver); } arch_initcall_sync(nsp_gpio_init); diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index 47613201269a..79c4e14a5a75 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -687,6 +687,7 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev, if (!info->functions) return -ENOMEM; + info->group_index = 0; if (flat_funcs) { info->ngroups = of_get_child_count(np); } else { diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 30389f4ccab4..c43b1e9a06af 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1652,12 +1652,15 @@ static int chv_pinctrl_probe(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP -static int chv_pinctrl_suspend(struct device *dev) +static int chv_pinctrl_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); + unsigned long flags; int i; + raw_spin_lock_irqsave(&chv_lock, flags); + pctrl->saved_intmask = readl(pctrl->regs + CHV_INTMASK); for (i = 0; i < pctrl->community->npins; i++) { @@ -1678,15 +1681,20 @@ static int chv_pinctrl_suspend(struct device *dev) ctx->padctrl1 = readl(reg); } + raw_spin_unlock_irqrestore(&chv_lock, flags); + return 0; } -static int chv_pinctrl_resume(struct device *dev) +static int chv_pinctrl_resume_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); + unsigned long flags; int i; + raw_spin_lock_irqsave(&chv_lock, flags); + /* * Mask all interrupts before restoring per-pin configuration * registers because we don't know in which state BIOS left them @@ -1731,12 +1739,15 @@ static int chv_pinctrl_resume(struct device *dev) chv_writel(0xffff, pctrl->regs + CHV_INTSTAT); chv_writel(pctrl->saved_intmask, pctrl->regs + CHV_INTMASK); + raw_spin_unlock_irqrestore(&chv_lock, flags); + return 0; } #endif static const struct dev_pm_ops chv_pinctrl_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend, chv_pinctrl_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend_noirq, + chv_pinctrl_resume_noirq) }; static const struct acpi_device_id chv_pinctrl_acpi_match[] = { diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 99da4cf91031..b7bb37167969 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -1512,7 +1512,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, if (info->irqmux_base || gpio_irq > 0) { err = gpiochip_irqchip_add(&bank->gpio_chip, &st_gpio_irqchip, 0, handle_simple_irq, - IRQ_TYPE_LEVEL_LOW); + IRQ_TYPE_NONE); if (err) { gpiochip_remove(&bank->gpio_chip); dev_info(dev, "could not add irqchip\n"); diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 200667f08c37..efc43711ff5c 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1092,9 +1092,11 @@ int stm32_pctl_probe(struct platform_device *pdev) return -EINVAL; } - ret = stm32_pctrl_dt_setup_irq(pdev, pctl); - if (ret) - return ret; + if (of_find_property(np, "interrupt-parent", NULL)) { + ret = stm32_pctrl_dt_setup_irq(pdev, pctl); + if (ret) + return ret; + } for_each_child_of_node(np, child) if (of_property_read_bool(child, "gpio-controller")) @@ -1078,6 +1078,17 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2) unsigned tail, pos, head; unsigned long flags; + if (kiocb->ki_flags & IOCB_WRITE) { + struct file *file = kiocb->ki_filp; + + /* + * Tell lockdep we inherited freeze protection from submission + * thread. + */ + __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE); + file_end_write(file); + } + /* * Special case handling for sync iocbs: * - events go directly into the iocb for fast handling @@ -1392,122 +1403,106 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) return -EINVAL; } -typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *); - -static int aio_setup_vectored_rw(int rw, char __user *buf, size_t len, - struct iovec **iovec, - bool compat, - struct iov_iter *iter) +static int aio_setup_rw(int rw, struct iocb *iocb, struct iovec **iovec, + bool vectored, bool compat, struct iov_iter *iter) { + void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf; + size_t len = iocb->aio_nbytes; + + if (!vectored) { + ssize_t ret = import_single_range(rw, buf, len, *iovec, iter); + *iovec = NULL; + return ret; + } #ifdef CONFIG_COMPAT if (compat) - return compat_import_iovec(rw, - (struct compat_iovec __user *)buf, - len, UIO_FASTIOV, iovec, iter); + return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec, + iter); #endif - return import_iovec(rw, (struct iovec __user *)buf, - len, UIO_FASTIOV, iovec, iter); + return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter); } -/* - * aio_run_iocb: - * Performs the initial checks and io submission. - */ -static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, - char __user *buf, size_t len, bool compat) +static inline ssize_t aio_ret(struct kiocb *req, ssize_t ret) +{ + switch (ret) { + case -EIOCBQUEUED: + return ret; + case -ERESTARTSYS: + case -ERESTARTNOINTR: + case -ERESTARTNOHAND: + case -ERESTART_RESTARTBLOCK: + /* + * There's no easy way to restart the syscall since other AIO's + * may be already running. Just fail this IO with EINTR. + */ + ret = -EINTR; + /*FALLTHRU*/ + default: + aio_complete(req, ret, 0); + return 0; + } +} + +static ssize_t aio_read(struct kiocb *req, struct iocb *iocb, bool vectored, + bool compat) { struct file *file = req->ki_filp; - ssize_t ret; - int rw; - fmode_t mode; - rw_iter_op *iter_op; struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; struct iov_iter iter; + ssize_t ret; - switch (opcode) { - case IOCB_CMD_PREAD: - case IOCB_CMD_PREADV: - mode = FMODE_READ; - rw = READ; - iter_op = file->f_op->read_iter; - goto rw_common; - - case IOCB_CMD_PWRITE: - case IOCB_CMD_PWRITEV: - mode = FMODE_WRITE; - rw = WRITE; - iter_op = file->f_op->write_iter; - goto rw_common; -rw_common: - if (unlikely(!(file->f_mode & mode))) - return -EBADF; - - if (!iter_op) - return -EINVAL; - - if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) - ret = aio_setup_vectored_rw(rw, buf, len, - &iovec, compat, &iter); - else { - ret = import_single_range(rw, buf, len, iovec, &iter); - iovec = NULL; - } - if (!ret) - ret = rw_verify_area(rw, file, &req->ki_pos, - iov_iter_count(&iter)); - if (ret < 0) { - kfree(iovec); - return ret; - } - - if (rw == WRITE) - file_start_write(file); - - ret = iter_op(req, &iter); - - if (rw == WRITE) - file_end_write(file); - kfree(iovec); - break; - - case IOCB_CMD_FDSYNC: - if (!file->f_op->aio_fsync) - return -EINVAL; - - ret = file->f_op->aio_fsync(req, 1); - break; + if (unlikely(!(file->f_mode & FMODE_READ))) + return -EBADF; + if (unlikely(!file->f_op->read_iter)) + return -EINVAL; - case IOCB_CMD_FSYNC: - if (!file->f_op->aio_fsync) - return -EINVAL; + ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter); + if (ret) + return ret; + ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter)); + if (!ret) + ret = aio_ret(req, file->f_op->read_iter(req, &iter)); + kfree(iovec); + return ret; +} - ret = file->f_op->aio_fsync(req, 0); - break; +static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored, + bool compat) +{ + struct file *file = req->ki_filp; + struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; + struct iov_iter iter; + ssize_t ret; - default: - pr_debug("EINVAL: no operation provided\n"); + if (unlikely(!(file->f_mode & FMODE_WRITE))) + return -EBADF; + if (unlikely(!file->f_op->write_iter)) return -EINVAL; - } - if (ret != -EIOCBQUEUED) { + ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter); + if (ret) + return ret; + ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter)); + if (!ret) { + req->ki_flags |= IOCB_WRITE; + file_start_write(file); + ret = aio_ret(req, file->f_op->write_iter(req, &iter)); /* - * There's no easy way to restart the syscall since other AIO's - * may be already running. Just fail this IO with EINTR. + * We release freeze protection in aio_complete(). Fool lockdep + * by telling it the lock got released so that it doesn't + * complain about held lock when we return to userspace. */ - if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR || - ret == -ERESTARTNOHAND || - ret == -ERESTART_RESTARTBLOCK)) - ret = -EINTR; - aio_complete(req, ret, 0); + __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE); } - - return 0; + kfree(iovec); + return ret; } static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, struct iocb *iocb, bool compat) { struct aio_kiocb *req; + struct file *file; ssize_t ret; /* enforce forwards compatibility on users */ @@ -1530,7 +1525,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, if (unlikely(!req)) return -EAGAIN; - req->common.ki_filp = fget(iocb->aio_fildes); + req->common.ki_filp = file = fget(iocb->aio_fildes); if (unlikely(!req->common.ki_filp)) { ret = -EBADF; goto out_put_req; @@ -1565,13 +1560,29 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, req->ki_user_iocb = user_iocb; req->ki_user_data = iocb->aio_data; - ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode, - (char __user *)(unsigned long)iocb->aio_buf, - iocb->aio_nbytes, - compat); - if (ret) - goto out_put_req; + get_file(file); + switch (iocb->aio_lio_opcode) { + case IOCB_CMD_PREAD: + ret = aio_read(&req->common, iocb, false, compat); + break; + case IOCB_CMD_PWRITE: + ret = aio_write(&req->common, iocb, false, compat); + break; + case IOCB_CMD_PREADV: + ret = aio_read(&req->common, iocb, true, compat); + break; + case IOCB_CMD_PWRITEV: + ret = aio_write(&req->common, iocb, true, compat); + break; + default: + pr_debug("invalid aio operation %d\n", iocb->aio_lio_opcode); + ret = -EINVAL; + break; + } + fput(file); + if (ret && ret != -EIOCBQUEUED) + goto out_put_req; return 0; out_put_req: put_reqs_available(ctx, 1); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 18630e800208..f995e3528a33 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1770,7 +1770,6 @@ const struct file_operations ceph_file_fops = { .fsync = ceph_fsync, .lock = ceph_lock, .flock = ceph_flock, - .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, .unlocked_ioctl = ceph_ioctl, .compat_ioctl = ceph_ioctl, diff --git a/fs/coredump.c b/fs/coredump.c index 281b768000e6..eb9c92c9b20f 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -1,6 +1,7 @@ #include <linux/slab.h> #include <linux/file.h> #include <linux/fdtable.h> +#include <linux/freezer.h> #include <linux/mm.h> #include <linux/stat.h> #include <linux/fcntl.h> @@ -423,7 +424,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state) if (core_waiters > 0) { struct core_thread *ptr; + freezer_do_not_count(); wait_for_completion(&core_state->startup); + freezer_count(); /* * Wait for all the threads to become inactive, so that * all the thread context (extended register state, like diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 7555ba889d1f..ebecfb8fba06 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -314,7 +314,8 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat /* Match the full socket address */ if (!rpc_cmp_addr_port(sap, clap)) /* Match all xprt_switch full socket addresses */ - if (!rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient, + if (IS_ERR(clp->cl_rpcclient) || + !rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient, sap)) continue; diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index c8162c660c44..5551e8ef67fd 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -98,7 +98,7 @@ rename_retry: return end; } namelen = strlen(base); - if (flags & NFS_PATH_CANONICAL) { + if (*end == '/') { /* Strip off excess slashes in base string */ while (namelen > 0 && base[namelen - 1] == '/') namelen--; diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index b62973045a3e..a61350f75c74 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c @@ -178,12 +178,14 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid, __must_hold(&tbl->slot_tbl_lock) { struct nfs4_slot *slot; + int ret; slot = nfs4_lookup_slot(tbl, slotid); - if (IS_ERR(slot)) - return PTR_ERR(slot); - *seq_nr = slot->seq_nr; - return 0; + ret = PTR_ERR_OR_ZERO(slot); + if (!ret) + *seq_nr = slot->seq_nr; + + return ret; } /* @@ -196,7 +198,7 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid, static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr) { - u32 cur_seq; + u32 cur_seq = 0; bool ret = false; spin_lock(&tbl->slot_tbl_lock); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 56b2d96f9103..259ef85f435a 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -146,6 +146,8 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, u32 id; int i; + if (fsinfo->nlayouttypes == 0) + goto out_no_driver; if (!(server->nfs_client->cl_exchange_flags & (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) { printk(KERN_ERR "NFS: %s: cl_exchange_flags 0x%x\n", diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index a18613579001..0ee19ecc982d 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1544,8 +1544,6 @@ const struct file_operations ntfs_dir_ops = { .iterate = ntfs_readdir, /* Read directory contents. */ #ifdef NTFS_RW .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ - /*.aio_fsync = ,*/ /* Sync all outstanding async - i/o operations on a kiocb. */ #endif /* NTFS_RW */ /*.ioctl = ,*/ /* Perform function on the mounted filesystem. */ diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index e7054e2ac922..3ecb9f337b7d 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -3699,7 +3699,7 @@ static void ocfs2_dx_dir_transfer_leaf(struct inode *dir, u32 split_hash, static int ocfs2_dx_dir_rebalance_credits(struct ocfs2_super *osb, struct ocfs2_dx_root_block *dx_root) { - int credits = ocfs2_clusters_to_blocks(osb->sb, 2); + int credits = ocfs2_clusters_to_blocks(osb->sb, 3); credits += ocfs2_calc_extend_credits(osb->sb, &dx_root->dr_list); credits += ocfs2_quota_trans_credits(osb->sb); diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index eb09aa026723..d484068ca716 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c @@ -141,6 +141,9 @@ static struct client_debug_mask client_debug_mask; */ static DEFINE_MUTEX(orangefs_debug_lock); +/* Used to protect data in ORANGEFS_KMOD_DEBUG_HELP_FILE */ +static DEFINE_MUTEX(orangefs_help_file_lock); + /* * initialize kmod debug operations, create orangefs debugfs dir and * ORANGEFS_KMOD_DEBUG_HELP_FILE. @@ -289,6 +292,8 @@ static void *help_start(struct seq_file *m, loff_t *pos) gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); + mutex_lock(&orangefs_help_file_lock); + if (*pos == 0) payload = m->private; @@ -305,6 +310,7 @@ static void *help_next(struct seq_file *m, void *v, loff_t *pos) static void help_stop(struct seq_file *m, void *p) { gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); + mutex_unlock(&orangefs_help_file_lock); } static int help_show(struct seq_file *m, void *v) @@ -610,32 +616,54 @@ out: * /sys/kernel/debug/orangefs/debug-help can be catted to * see all the available kernel and client debug keywords. * - * When the kernel boots, we have no idea what keywords the + * When orangefs.ko initializes, we have no idea what keywords the * client supports, nor their associated masks. * - * We pass through this function once at boot and stamp a + * We pass through this function once at module-load and stamp a * boilerplate "we don't know" message for the client in the * debug-help file. We pass through here again when the client * starts and then we can fill out the debug-help file fully. * * The client might be restarted any number of times between - * reboots, we only build the debug-help file the first time. + * module reloads, we only build the debug-help file the first time. */ int orangefs_prepare_debugfs_help_string(int at_boot) { - int rc = -EINVAL; - int i; - int byte_count = 0; char *client_title = "Client Debug Keywords:\n"; char *kernel_title = "Kernel Debug Keywords:\n"; + size_t string_size = DEBUG_HELP_STRING_SIZE; + size_t result_size; + size_t i; + char *new; + int rc = -EINVAL; gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); - if (at_boot) { - byte_count += strlen(HELP_STRING_UNINITIALIZED); + if (at_boot) client_title = HELP_STRING_UNINITIALIZED; - } else { - /* + + /* build a new debug_help_string. */ + new = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); + if (!new) { + rc = -ENOMEM; + goto out; + } + + /* + * strlcat(dst, src, size) will append at most + * "size - strlen(dst) - 1" bytes of src onto dst, + * null terminating the result, and return the total + * length of the string it tried to create. + * + * We'll just plow through here building our new debug + * help string and let strlcat take care of assuring that + * dst doesn't overflow. + */ + strlcat(new, client_title, string_size); + + if (!at_boot) { + + /* * fill the client keyword/mask array and remember * how many elements there were. */ @@ -644,64 +672,40 @@ int orangefs_prepare_debugfs_help_string(int at_boot) if (cdm_element_count <= 0) goto out; - /* Count the bytes destined for debug_help_string. */ - byte_count += strlen(client_title); - for (i = 0; i < cdm_element_count; i++) { - byte_count += strlen(cdm_array[i].keyword + 2); - if (byte_count >= DEBUG_HELP_STRING_SIZE) { - pr_info("%s: overflow 1!\n", __func__); - goto out; - } + strlcat(new, "\t", string_size); + strlcat(new, cdm_array[i].keyword, string_size); + strlcat(new, "\n", string_size); } - - gossip_debug(GOSSIP_UTILS_DEBUG, - "%s: cdm_element_count:%d:\n", - __func__, - cdm_element_count); } - byte_count += strlen(kernel_title); + strlcat(new, "\n", string_size); + strlcat(new, kernel_title, string_size); + for (i = 0; i < num_kmod_keyword_mask_map; i++) { - byte_count += - strlen(s_kmod_keyword_mask_map[i].keyword + 2); - if (byte_count >= DEBUG_HELP_STRING_SIZE) { - pr_info("%s: overflow 2!\n", __func__); - goto out; - } + strlcat(new, "\t", string_size); + strlcat(new, s_kmod_keyword_mask_map[i].keyword, string_size); + result_size = strlcat(new, "\n", string_size); } - /* build debug_help_string. */ - debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); - if (!debug_help_string) { - rc = -ENOMEM; + /* See if we tried to put too many bytes into "new"... */ + if (result_size >= string_size) { + kfree(new); goto out; } - strcat(debug_help_string, client_title); - - if (!at_boot) { - for (i = 0; i < cdm_element_count; i++) { - strcat(debug_help_string, "\t"); - strcat(debug_help_string, cdm_array[i].keyword); - strcat(debug_help_string, "\n"); - } - } - - strcat(debug_help_string, "\n"); - strcat(debug_help_string, kernel_title); - - for (i = 0; i < num_kmod_keyword_mask_map; i++) { - strcat(debug_help_string, "\t"); - strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword); - strcat(debug_help_string, "\n"); + if (at_boot) { + debug_help_string = new; + } else { + mutex_lock(&orangefs_help_file_lock); + memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE); + strlcat(debug_help_string, new, string_size); + mutex_unlock(&orangefs_help_file_lock); } rc = 0; -out: - - return rc; +out: return rc; } @@ -959,8 +963,12 @@ int orangefs_debugfs_new_client_string(void __user *arg) ret = copy_from_user(&client_debug_array_string, (void __user *)arg, ORANGEFS_MAX_DEBUG_STRING_LEN); - if (ret != 0) + + if (ret != 0) { + pr_info("%s: CLIENT_STRING: copy_from_user failed\n", + __func__); return -EIO; + } /* * The real client-core makes an effort to ensure @@ -975,45 +983,18 @@ int orangefs_debugfs_new_client_string(void __user *arg) client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = '\0'; - if (ret != 0) { - pr_info("%s: CLIENT_STRING: copy_from_user failed\n", - __func__); - return -EIO; - } - pr_info("%s: client debug array string has been received.\n", __func__); if (!help_string_initialized) { - /* Free the "we don't know yet" default string... */ - kfree(debug_help_string); - - /* build a proper debug help string */ + /* Build a proper debug help string. */ if (orangefs_prepare_debugfs_help_string(0)) { gossip_err("%s: no debug help string \n", __func__); return -EIO; } - /* Replace the boilerplate boot-time debug-help file. */ - debugfs_remove(help_file_dentry); - - help_file_dentry = - debugfs_create_file( - ORANGEFS_KMOD_DEBUG_HELP_FILE, - 0444, - debug_dir, - debug_help_string, - &debug_help_fops); - - if (!help_file_dentry) { - gossip_err("%s: debugfs_create_file failed for" - " :%s:!\n", - __func__, - ORANGEFS_KMOD_DEBUG_HELP_FILE); - return -EIO; - } } debug_mask_to_string(&client_debug_mask, 1); diff --git a/fs/orangefs/orangefs-mod.c b/fs/orangefs/orangefs-mod.c index 2e5b03065f34..4113eb0495bf 100644 --- a/fs/orangefs/orangefs-mod.c +++ b/fs/orangefs/orangefs-mod.c @@ -124,7 +124,7 @@ static int __init orangefs_init(void) * unknown at boot time. * * orangefs_prepare_debugfs_help_string will be used again - * later to rebuild the debug-help file after the client starts + * later to rebuild the debug-help-string after the client starts * and passes along the needed info. The argument signifies * which time orangefs_prepare_debugfs_help_string is being * called. @@ -152,7 +152,9 @@ static int __init orangefs_init(void) ret = register_filesystem(&orangefs_fs_type); if (ret == 0) { - pr_info("orangefs: module version %s loaded\n", ORANGEFS_VERSION); + pr_info("%s: module version %s loaded\n", + __func__, + ORANGEFS_VERSION); ret = 0; goto out; } diff --git a/fs/splice.c b/fs/splice.c index 153d4f3bd441..dcaf185a5731 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -299,13 +299,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, { struct iov_iter to; struct kiocb kiocb; - loff_t isize; int idx, ret; - isize = i_size_read(in->f_mapping->host); - if (unlikely(*ppos >= isize)) - return 0; - iov_iter_pipe(&to, ITER_PIPE | READ, pipe, len); idx = to.idx; init_sync_kiocb(&kiocb, in); diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 613c5cf19436..5c2929f94bd3 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -199,9 +199,9 @@ xfs_defer_intake_work( struct xfs_defer_pending *dfp; list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { - trace_xfs_defer_intake_work(tp->t_mountp, dfp); dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_count); + trace_xfs_defer_intake_work(tp->t_mountp, dfp); list_sort(tp->t_mountp, &dfp->dfp_work, dfp->dfp_type->diff_items); list_for_each(li, &dfp->dfp_work) @@ -221,21 +221,14 @@ xfs_defer_trans_abort( struct xfs_defer_pending *dfp; trace_xfs_defer_trans_abort(tp->t_mountp, dop); - /* - * If the transaction was committed, drop the intent reference - * since we're bailing out of here. The other reference is - * dropped when the intent hits the AIL. If the transaction - * was not committed, the intent is freed by the intent item - * unlock handler on abort. - */ - if (!dop->dop_committed) - return; - /* Abort intent items. */ + /* Abort intent items that don't have a done item. */ list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { trace_xfs_defer_pending_abort(tp->t_mountp, dfp); - if (!dfp->dfp_done) + if (dfp->dfp_intent && !dfp->dfp_done) { dfp->dfp_type->abort_intent(dfp->dfp_intent); + dfp->dfp_intent = NULL; + } } /* Shut down FS. */ diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index 40e887068da2..0504ef8f3aa3 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -118,9 +118,9 @@ do { \ #define this_cpu_generic_read(pcp) \ ({ \ typeof(pcp) __ret; \ - preempt_disable(); \ + preempt_disable_notrace(); \ __ret = raw_cpu_generic_read(pcp); \ - preempt_enable(); \ + preempt_enable_notrace(); \ __ret; \ }) diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index af0254c09424..4df64a1fc09e 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -14,6 +14,8 @@ * [_sdata, _edata]: contains .data.* sections, may also contain .rodata.* * and/or .init.* sections. * [__start_rodata, __end_rodata]: contains .rodata.* sections + * [__start_data_ro_after_init, __end_data_ro_after_init]: + * contains data.ro_after_init section * [__init_begin, __init_end]: contains .init.* sections, but .init.text.* * may be out of this range on some architectures. * [_sinittext, _einittext]: contains .init.text.* sections @@ -31,6 +33,7 @@ extern char _data[], _sdata[], _edata[]; extern char __bss_start[], __bss_stop[]; extern char __init_begin[], __init_end[]; extern char _sinittext[], _einittext[]; +extern char __start_data_ro_after_init[], __end_data_ro_after_init[]; extern char _end[]; extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[]; extern char __kprobes_text_start[], __kprobes_text_end[]; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 30747960bc54..31e1d639abed 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -259,7 +259,10 @@ * own by defining an empty RO_AFTER_INIT_DATA. */ #ifndef RO_AFTER_INIT_DATA -#define RO_AFTER_INIT_DATA *(.data..ro_after_init) +#define RO_AFTER_INIT_DATA \ + __start_data_ro_after_init = .; \ + *(.data..ro_after_init) \ + __end_data_ro_after_init = .; #endif /* diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 96337b15a60d..a8e66344bacc 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -258,6 +258,8 @@ struct ceph_watch_item { struct ceph_entity_addr addr; }; +#define CEPH_LINGER_ID_START 0xffff000000000000ULL + struct ceph_osd_client { struct ceph_client *client; diff --git a/include/linux/console.h b/include/linux/console.h index 3672809234a7..d530c4627e54 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -173,12 +173,6 @@ static inline void console_sysfs_notify(void) #endif extern bool console_suspend_enabled; -#ifdef CONFIG_OF -extern void console_set_by_of(void); -#else -static inline void console_set_by_of(void) {} -#endif - /* Suspend and resume console messages over PM events */ extern void suspend_console(void); extern void resume_console(void); diff --git a/include/linux/frontswap.h b/include/linux/frontswap.h index c46d2aa16d81..1d18af034554 100644 --- a/include/linux/frontswap.h +++ b/include/linux/frontswap.h @@ -106,8 +106,9 @@ static inline void frontswap_invalidate_area(unsigned type) static inline void frontswap_init(unsigned type, unsigned long *map) { - if (frontswap_enabled()) - __frontswap_init(type, map); +#ifdef CONFIG_FRONTSWAP + __frontswap_init(type, map); +#endif } #endif /* _LINUX_FRONTSWAP_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 16d2b6e874d6..dc0478c07b2a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -321,6 +321,7 @@ struct writeback_control; #define IOCB_HIPRI (1 << 3) #define IOCB_DSYNC (1 << 4) #define IOCB_SYNC (1 << 5) +#define IOCB_WRITE (1 << 6) struct kiocb { struct file *ki_filp; @@ -1709,7 +1710,6 @@ struct file_operations { int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); - int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index 33d00a4ce656..819d895edfdc 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -18,12 +18,6 @@ #include <linux/types.h> #include <sound/asound.h> -#ifndef __KERNEL__ -#error This API is an early revision and not enabled in the current -#error kernel release, it will be enabled in a future kernel version -#error with incompatible changes to what is here. -#endif - /* * Maximum number of channels topology kcontrol can represent. */ diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index de08fc90baaf..5028f4fd504a 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -253,17 +253,6 @@ static int preferred_console = -1; int console_set_on_cmdline; EXPORT_SYMBOL(console_set_on_cmdline); -#ifdef CONFIG_OF -static bool of_specified_console; - -void console_set_by_of(void) -{ - of_specified_console = true; -} -#else -# define of_specified_console false -#endif - /* Flag: console code may call schedule() */ static int console_may_schedule; @@ -2657,7 +2646,7 @@ void register_console(struct console *newcon) * didn't select a console we take the first one * that registers here. */ - if (preferred_console < 0 && !of_specified_console) { + if (preferred_console < 0) { if (newcon->index < 0) newcon->index = 0; if (newcon->setup == NULL || diff --git a/lib/stackdepot.c b/lib/stackdepot.c index 4d830e299989..f87d138e9672 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -192,6 +192,7 @@ void depot_fetch_stack(depot_stack_handle_t handle, struct stack_trace *trace) trace->entries = stack->entries; trace->skip = 0; } +EXPORT_SYMBOL_GPL(depot_fetch_stack); /** * depot_save_stack - save stack in a stack depot. @@ -283,3 +284,4 @@ exit: fast_exit: return retval; } +EXPORT_SYMBOL_GPL(depot_save_stack); @@ -385,6 +385,9 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) bitmap_maxno = cma_bitmap_maxno(cma); bitmap_count = cma_bitmap_pages_to_bits(cma, count); + if (bitmap_count > bitmap_maxno) + return NULL; + for (;;) { mutex_lock(&cma->lock); bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap, diff --git a/mm/filemap.c b/mm/filemap.c index c7fe2f16503f..50b52fe51937 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1732,6 +1732,9 @@ find_page: if (inode->i_blkbits == PAGE_SHIFT || !mapping->a_ops->is_partially_uptodate) goto page_not_up_to_date; + /* pipes can't handle partially uptodate pages */ + if (unlikely(iter->type & ITER_PIPE)) + goto page_not_up_to_date; if (!trylock_page(page)) goto page_not_up_to_date; /* Did it get truncated before we got the lock? */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ec49d9ef1eef..418bf01a50ed 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1826,11 +1826,17 @@ static void return_unused_surplus_pages(struct hstate *h, * is not the case is if a reserve map was changed between calls. It * is the responsibility of the caller to notice the difference and * take appropriate action. + * + * vma_add_reservation is used in error paths where a reservation must + * be restored when a newly allocated huge page must be freed. It is + * to be called after calling vma_needs_reservation to determine if a + * reservation exists. */ enum vma_resv_mode { VMA_NEEDS_RESV, VMA_COMMIT_RESV, VMA_END_RESV, + VMA_ADD_RESV, }; static long __vma_reservation_common(struct hstate *h, struct vm_area_struct *vma, unsigned long addr, @@ -1856,6 +1862,14 @@ static long __vma_reservation_common(struct hstate *h, region_abort(resv, idx, idx + 1); ret = 0; break; + case VMA_ADD_RESV: + if (vma->vm_flags & VM_MAYSHARE) + ret = region_add(resv, idx, idx + 1); + else { + region_abort(resv, idx, idx + 1); + ret = region_del(resv, idx, idx + 1); + } + break; default: BUG(); } @@ -1903,6 +1917,56 @@ static void vma_end_reservation(struct hstate *h, (void)__vma_reservation_common(h, vma, addr, VMA_END_RESV); } +static long vma_add_reservation(struct hstate *h, + struct vm_area_struct *vma, unsigned long addr) +{ + return __vma_reservation_common(h, vma, addr, VMA_ADD_RESV); +} + +/* + * This routine is called to restore a reservation on error paths. In the + * specific error paths, a huge page was allocated (via alloc_huge_page) + * and is about to be freed. If a reservation for the page existed, + * alloc_huge_page would have consumed the reservation and set PagePrivate + * in the newly allocated page. When the page is freed via free_huge_page, + * the global reservation count will be incremented if PagePrivate is set. + * However, free_huge_page can not adjust the reserve map. Adjust the + * reserve map here to be consistent with global reserve count adjustments + * to be made by free_huge_page. + */ +static void restore_reserve_on_error(struct hstate *h, + struct vm_area_struct *vma, unsigned long address, + struct page *page) +{ + if (unlikely(PagePrivate(page))) { + long rc = vma_needs_reservation(h, vma, address); + + if (unlikely(rc < 0)) { + /* + * Rare out of memory condition in reserve map + * manipulation. Clear PagePrivate so that + * global reserve count will not be incremented + * by free_huge_page. This will make it appear + * as though the reservation for this page was + * consumed. This may prevent the task from + * faulting in the page at a later time. This + * is better than inconsistent global huge page + * accounting of reserve counts. + */ + ClearPagePrivate(page); + } else if (rc) { + rc = vma_add_reservation(h, vma, address); + if (unlikely(rc < 0)) + /* + * See above comment about rare out of + * memory condition. + */ + ClearPagePrivate(page); + } else + vma_end_reservation(h, vma, address); + } +} + struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr, int avoid_reserve) { @@ -3498,6 +3562,7 @@ retry_avoidcopy: spin_unlock(ptl); mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); out_release_all: + restore_reserve_on_error(h, vma, address, new_page); put_page(new_page); out_release_old: put_page(old_page); @@ -3680,6 +3745,7 @@ backout: spin_unlock(ptl); backout_unlocked: unlock_page(page); + restore_reserve_on_error(h, vma, address, page); put_page(page); goto out; } diff --git a/mm/kmemleak.c b/mm/kmemleak.c index e5355a5b423f..d1380ed93fdf 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1414,6 +1414,7 @@ static void kmemleak_scan(void) /* data/bss scanning */ scan_large_block(_sdata, _edata); scan_large_block(__bss_start, __bss_stop); + scan_large_block(__start_data_ro_after_init, __end_data_ro_after_init); #ifdef CONFIG_SMP /* per-cpu sections scanning */ diff --git a/mm/memory-failure.c b/mm/memory-failure.c index de88f33519c0..19e796d36a62 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1112,10 +1112,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) } if (!PageHuge(p) && PageTransHuge(hpage)) { - lock_page(hpage); - if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) { - unlock_page(hpage); - if (!PageAnon(hpage)) + lock_page(p); + if (!PageAnon(p) || unlikely(split_huge_page(p))) { + unlock_page(p); + if (!PageAnon(p)) pr_err("Memory failure: %#lx: non anonymous thp\n", pfn); else @@ -1126,9 +1126,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) put_hwpoison_page(p); return -EBUSY; } - unlock_page(hpage); - get_hwpoison_page(p); - put_hwpoison_page(hpage); + unlock_page(p); VM_BUG_ON_PAGE(!page_count(p), p); hpage = compound_head(p); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 072d791dce2d..6de9440e3ae2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3658,7 +3658,7 @@ retry: /* Make sure we know about allocations which stall for too long */ if (time_after(jiffies, alloc_start + stall_timeout)) { warn_alloc(gfp_mask, - "page alloction stalls for %ums, order:%u\n", + "page allocation stalls for %ums, order:%u", jiffies_to_msecs(jiffies-alloc_start), order); stall_timeout += 10 * HZ; } diff --git a/mm/shmem.c b/mm/shmem.c index ad7813d73ea7..166ebf5d2bce 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1483,6 +1483,8 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp, copy_highpage(newpage, oldpage); flush_dcache_page(newpage); + __SetPageLocked(newpage); + __SetPageSwapBacked(newpage); SetPageUptodate(newpage); set_page_private(newpage, swap_index); SetPageSwapCache(newpage); diff --git a/mm/slab_common.c b/mm/slab_common.c index 71f0b28a1bec..329b03843863 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -533,8 +533,8 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg, s = create_cache(cache_name, root_cache->object_size, root_cache->size, root_cache->align, - root_cache->flags, root_cache->ctor, - memcg, root_cache); + root_cache->flags & CACHE_CREATE_MASK, + root_cache->ctor, memcg, root_cache); /* * If we could not create a memcg cache, do not complain, because * that's not critical at all as we can always proceed with the root diff --git a/mm/swapfile.c b/mm/swapfile.c index 2210de290b54..f30438970cd1 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2224,6 +2224,8 @@ static unsigned long read_swap_header(struct swap_info_struct *p, swab32s(&swap_header->info.version); swab32s(&swap_header->info.last_page); swab32s(&swap_header->info.nr_badpages); + if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) + return 0; for (i = 0; i < swap_header->info.nr_badpages; i++) swab32s(&swap_header->info.badpages[i]); } diff --git a/net/ceph/ceph_fs.c b/net/ceph/ceph_fs.c index 7d54e944de5e..dcbe67ff3e2b 100644 --- a/net/ceph/ceph_fs.c +++ b/net/ceph/ceph_fs.c @@ -34,7 +34,8 @@ void ceph_file_layout_from_legacy(struct ceph_file_layout *fl, fl->stripe_count = le32_to_cpu(legacy->fl_stripe_count); fl->object_size = le32_to_cpu(legacy->fl_object_size); fl->pool_id = le32_to_cpu(legacy->fl_pg_pool); - if (fl->pool_id == 0) + if (fl->pool_id == 0 && fl->stripe_unit == 0 && + fl->stripe_count == 0 && fl->object_size == 0) fl->pool_id = -1; } EXPORT_SYMBOL(ceph_file_layout_from_legacy); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index d9bf7a1d0a58..e6ae15bc41b7 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -4094,6 +4094,7 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) osd_init(&osdc->homeless_osd); osdc->homeless_osd.o_osdc = osdc; osdc->homeless_osd.o_osd = CEPH_HOMELESS_OSD; + osdc->last_linger_id = CEPH_LINGER_ID_START; osdc->linger_requests = RB_ROOT; osdc->map_checks = RB_ROOT; osdc->linger_map_checks = RB_ROOT; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 34dd7b26ee5f..62a482790937 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -2753,14 +2753,18 @@ EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout); void rpc_clnt_xprt_switch_put(struct rpc_clnt *clnt) { + rcu_read_lock(); xprt_switch_put(rcu_dereference(clnt->cl_xpi.xpi_xpswitch)); + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_put); void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt) { + rcu_read_lock(); rpc_xprt_switch_add_xprt(rcu_dereference(clnt->cl_xpi.xpi_xpswitch), xprt); + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt); @@ -2770,9 +2774,8 @@ bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt, struct rpc_xprt_switch *xps; bool ret; - xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch); - rcu_read_lock(); + xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch); ret = rpc_xprt_switch_has_addr(xps, sap); rcu_read_unlock(); return ret; diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 210949562786..26b26beef2d4 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c @@ -44,18 +44,20 @@ * being done. * * When the underlying transport disconnects, MRs are left in one of - * three states: + * four states: * * INVALID: The MR was not in use before the QP entered ERROR state. - * (Or, the LOCAL_INV WR has not completed or flushed yet). - * - * STALE: The MR was being registered or unregistered when the QP - * entered ERROR state, and the pending WR was flushed. * * VALID: The MR was registered before the QP entered ERROR state. * - * When frwr_op_map encounters STALE and VALID MRs, they are recovered - * with ib_dereg_mr and then are re-initialized. Beause MR recovery + * FLUSHED_FR: The MR was being registered when the QP entered ERROR + * state, and the pending WR was flushed. + * + * FLUSHED_LI: The MR was being invalidated when the QP entered ERROR + * state, and the pending WR was flushed. + * + * When frwr_op_map encounters FLUSHED and VALID MRs, they are recovered + * with ib_dereg_mr and then are re-initialized. Because MR recovery * allocates fresh resources, it is deferred to a workqueue, and the * recovered MRs are placed back on the rb_mws list when recovery is * complete. frwr_op_map allocates another MR for the current RPC while @@ -177,12 +179,15 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r) static void frwr_op_recover_mr(struct rpcrdma_mw *mw) { + enum rpcrdma_frmr_state state = mw->frmr.fr_state; struct rpcrdma_xprt *r_xprt = mw->mw_xprt; struct rpcrdma_ia *ia = &r_xprt->rx_ia; int rc; rc = __frwr_reset_mr(ia, mw); - ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir); + if (state != FRMR_FLUSHED_LI) + ib_dma_unmap_sg(ia->ri_device, + mw->mw_sg, mw->mw_nents, mw->mw_dir); if (rc) goto out_release; @@ -262,10 +267,8 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt) } static void -__frwr_sendcompletion_flush(struct ib_wc *wc, struct rpcrdma_frmr *frmr, - const char *wr) +__frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr) { - frmr->fr_state = FRMR_IS_STALE; if (wc->status != IB_WC_WR_FLUSH_ERR) pr_err("rpcrdma: %s: %s (%u/0x%x)\n", wr, ib_wc_status_msg(wc->status), @@ -288,7 +291,8 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc) if (wc->status != IB_WC_SUCCESS) { cqe = wc->wr_cqe; frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); - __frwr_sendcompletion_flush(wc, frmr, "fastreg"); + frmr->fr_state = FRMR_FLUSHED_FR; + __frwr_sendcompletion_flush(wc, "fastreg"); } } @@ -308,7 +312,8 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc) if (wc->status != IB_WC_SUCCESS) { cqe = wc->wr_cqe; frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); - __frwr_sendcompletion_flush(wc, frmr, "localinv"); + frmr->fr_state = FRMR_FLUSHED_LI; + __frwr_sendcompletion_flush(wc, "localinv"); } } @@ -328,8 +333,10 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc) /* WARNING: Only wr_cqe and status are reliable at this point */ cqe = wc->wr_cqe; frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); - if (wc->status != IB_WC_SUCCESS) - __frwr_sendcompletion_flush(wc, frmr, "localinv"); + if (wc->status != IB_WC_SUCCESS) { + frmr->fr_state = FRMR_FLUSHED_LI; + __frwr_sendcompletion_flush(wc, "localinv"); + } complete(&frmr->fr_linv_done); } diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 0d35b761c883..6e1bba358203 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -216,7 +216,8 @@ struct rpcrdma_rep { enum rpcrdma_frmr_state { FRMR_IS_INVALID, /* ready to be used */ FRMR_IS_VALID, /* in use */ - FRMR_IS_STALE, /* failed completion */ + FRMR_FLUSHED_FR, /* flushed FASTREG WR */ + FRMR_FLUSHED_LI, /* flushed LOCALINV WR */ }; struct rpcrdma_frmr { diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 53449a6ff6aa..7c321a603b07 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -36,6 +36,7 @@ warning-2 += -Wshadow warning-2 += $(call cc-option, -Wlogical-op) warning-2 += $(call cc-option, -Wmissing-field-initializers) warning-2 += $(call cc-option, -Wsign-compare) +warning-2 += $(call cc-option, -Wmaybe-uninitialized) warning-3 := -Wbad-function-cast warning-3 += -Wcast-qual diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index dd779c40c8e6..3b1b13818d59 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -17,4 +17,8 @@ endif ifdef CONFIG_UBSAN_NULL CFLAGS_UBSAN += $(call cc-option, -fsanitize=null) endif + + # -fsanitize=* options makes GCC less smart than usual and + # increase number of 'maybe-uninitialized false-positives + CFLAGS_UBSAN += $(call cc-option, -Wno-maybe-uninitialized) endif diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter index 19f5adfd877d..d9ff038c1b28 100755 --- a/scripts/bloat-o-meter +++ b/scripts/bloat-o-meter @@ -8,6 +8,9 @@ # of the GNU General Public License, incorporated herein by reference. import sys, os, re +from signal import signal, SIGPIPE, SIG_DFL + +signal(SIGPIPE, SIG_DFL) if len(sys.argv) != 3: sys.stderr.write("usage: %s file1 file2\n" % sys.argv[0]) diff --git a/sound/core/info.c b/sound/core/info.c index 895362a696c9..8ab72e0f5932 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -325,10 +325,15 @@ static ssize_t snd_info_text_entry_write(struct file *file, size_t next; int err = 0; + if (!entry->c.text.write) + return -EIO; pos = *offset; if (!valid_pos(pos, count)) return -EIO; next = pos + count; + /* don't handle too large text inputs */ + if (next > 16 * 1024) + return -EIO; mutex_lock(&entry->access); buf = data->wbuffer; if (!buf) { @@ -366,7 +371,9 @@ static int snd_info_seq_show(struct seq_file *seq, void *p) struct snd_info_private_data *data = seq->private; struct snd_info_entry *entry = data->entry; - if (entry->c.text.read) { + if (!entry->c.text.read) { + return -EIO; + } else { data->rbuffer->buffer = (char *)seq; /* XXX hack! */ entry->c.text.read(entry, data->rbuffer); } diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 18baea2f7d65..84f86745c30e 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -148,11 +148,11 @@ SND_SOC_DAPM_OUTPUT("AOUTR"), }; static const struct snd_soc_dapm_route cs4270_dapm_routes[] = { - { "Capture", NULL, "AINA" }, - { "Capture", NULL, "AINB" }, + { "Capture", NULL, "AINL" }, + { "Capture", NULL, "AINR" }, - { "AOUTA", NULL, "Playback" }, - { "AOUTB", NULL, "Playback" }, + { "AOUTL", NULL, "Playback" }, + { "AOUTR", NULL, "Playback" }, }; /** diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 1152aa5e7c39..cf37936bfe3a 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -880,7 +880,8 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), /* DAI */ - SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, DA7219_DAI_TDM_CTRL, + DA7219_DAI_OE_SHIFT, DA7219_NO_INVERT), SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0), /* Output Muxes */ diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index b904492d7744..90b5948e0ff3 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -364,7 +364,12 @@ static int hdmi_of_xlate_dai_name(struct snd_soc_component *component, struct of_phandle_args *args, const char **dai_name) { - int id = args->args[0]; + int id; + + if (args->args_count) + id = args->args[0]; + else + id = 0; if (id < ARRAY_SIZE(hdmi_dai_name)) { *dai_name = hdmi_dai_name[id]; diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 55558643166f..2db8179047ae 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -249,6 +249,11 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) snd_soc_dapm_force_enable_pin(dapm, "LDO1"); snd_soc_dapm_sync(dapm); + regmap_update_bits(rt298->regmap, + RT298_POWER_CTRL1, 0x1001, 0); + regmap_update_bits(rt298->regmap, + RT298_POWER_CTRL2, 0x4, 0x4); + regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24); msleep(50); diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 01a18d88f1eb..00ff2788879e 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1547,11 +1547,11 @@ static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert) msleep(sleep_time[i]); val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) & 0x0003; + dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n", + __func__, val, sleep_time[i]); i++; if (val == 0x1 || val == 0x2 || val == 0x3) break; - dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n", - __func__, val, sleep_time[i]); } dev_dbg(codec->dev, "%s val = %d\n", __func__, val); switch (val) { diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index 7b31ee9b82bc..d6e00c77edcd 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -424,7 +424,7 @@ static const struct snd_soc_dai_ops stih407_dac_ops = { static const struct regmap_config stih407_sas_regmap = { .reg_bits = 32, .val_bits = 32, - + .fast_io = true, .max_register = STIH407_AUDIO_DAC_CTRL, .reg_defaults = stih407_sas_reg_defaults, .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults), diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index df5e5cb33baa..810369f687d7 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -341,20 +341,9 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec, return ret; } } - - gpiod_set_value(priv->pdn_gpio, 0); - usleep_range(5000, 6000); - - regcache_cache_only(priv->regmap, false); - ret = regcache_sync(priv->regmap); - if (ret) - return ret; } break; case SND_SOC_BIAS_OFF: - regcache_cache_only(priv->regmap, true); - gpiod_set_value(priv->pdn_gpio, 1); - if (!IS_ERR(priv->mclk)) clk_disable_unprepare(priv->mclk); break; @@ -401,16 +390,6 @@ static const struct snd_kcontrol_new tas5711_controls[] = { TAS571X_SOFT_MUTE_REG, TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 1, 1), - - SOC_DOUBLE_R_RANGE("CH1 Mixer Volume", - TAS5717_CH1_LEFT_CH_MIX_REG, - TAS5717_CH1_RIGHT_CH_MIX_REG, - 16, 0, 0x80, 0), - - SOC_DOUBLE_R_RANGE("CH2 Mixer Volume", - TAS5717_CH2_LEFT_CH_MIX_REG, - TAS5717_CH2_RIGHT_CH_MIX_REG, - 16, 0, 0x80, 0), }; static const struct regmap_range tas571x_readonly_regs_range[] = { @@ -488,6 +467,16 @@ static const struct snd_kcontrol_new tas5717_controls[] = { TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 1, 1), + SOC_DOUBLE_R_RANGE("CH1 Mixer Volume", + TAS5717_CH1_LEFT_CH_MIX_REG, + TAS5717_CH1_RIGHT_CH_MIX_REG, + 16, 0, 0x80, 0), + + SOC_DOUBLE_R_RANGE("CH2 Mixer Volume", + TAS5717_CH2_LEFT_CH_MIX_REG, + TAS5717_CH2_RIGHT_CH_MIX_REG, + 16, 0, 0x80, 0), + /* * The biquads are named according to the register names. * Please note that TI's TAS57xx Graphical Development Environment @@ -747,13 +736,14 @@ static int tas571x_i2c_probe(struct i2c_client *client, /* pulse the active low reset line for ~100us */ usleep_range(100, 200); gpiod_set_value(priv->reset_gpio, 0); - usleep_range(12000, 20000); + usleep_range(13500, 20000); } ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0); if (ret) return ret; + usleep_range(50000, 60000); memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); priv->codec_driver.component_driver.controls = priv->chip->controls; @@ -770,9 +760,6 @@ static int tas571x_i2c_probe(struct i2c_client *client, return ret; } - regcache_cache_only(priv->regmap, true); - gpiod_set_value(priv->pdn_gpio, 1); - return snd_soc_register_codec(&client->dev, &priv->codec_driver, &tas571x_dai, 1); } diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 26eb5a0a5575..fd5d1e091038 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -47,6 +47,7 @@ config SND_SOC_INTEL_SST_MATCH config SND_SOC_INTEL_HASWELL tristate + select SND_SOC_INTEL_SST_FIRMWARE config SND_SOC_INTEL_BAYTRAIL tristate @@ -56,7 +57,6 @@ config SND_SOC_INTEL_HASWELL_MACH depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM depends on DW_DMAC_CORE select SND_SOC_INTEL_SST - select SND_SOC_INTEL_SST_FIRMWARE select SND_SOC_INTEL_HASWELL select SND_SOC_RT5640 help @@ -138,7 +138,6 @@ config SND_SOC_INTEL_BROADWELL_MACH I2C_DESIGNWARE_PLATFORM depends on DW_DMAC_CORE select SND_SOC_INTEL_SST - select SND_SOC_INTEL_SST_FIRMWARE select SND_SOC_INTEL_HASWELL select SND_SOC_RT286 help diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index ba5c0d71720a..0a88537ca58a 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -416,6 +416,7 @@ static const struct dmi_system_id cht_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Surface 3"), }, }, + { } }; diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 6532b8f0ab2f..865a21e557cc 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -130,8 +130,8 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) */ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, &broxton_headset, - NULL, 0); + SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, + &broxton_headset, NULL, 0); if (ret) { dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 2989c164dafe..06fa5e85dd0e 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -674,7 +674,7 @@ static int skl_probe(struct pci_dev *pci, if (skl->nhlt == NULL) { err = -ENODEV; - goto out_free; + goto out_display_power_off; } skl_nhlt_update_topology_bin(skl); @@ -746,6 +746,9 @@ out_mach_free: skl_machine_device_unregister(skl); out_nhlt_free: skl_nhlt_free(skl->nhlt); +out_display_power_off: + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + snd_hdac_display_power(bus, false); out_free: skl->init_failed = 1; skl_free(ebus); @@ -785,8 +788,7 @@ static void skl_remove(struct pci_dev *pci) release_firmware(skl->tplg); - if (pci_dev_run_wake(pci)) - pm_runtime_get_noresume(&pci->dev); + pm_runtime_get_noresume(&pci->dev); /* codec removal, invoke bus_device_remove */ snd_hdac_ext_bus_device_remove(ebus); diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f2bf8661dd21..823b5a236d8d 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -208,7 +208,7 @@ config SND_PXA2XX_SOC_IMOTE2 config SND_MMP_SOC_BROWNSTONE tristate "SoC Audio support for Marvell Brownstone" - depends on SND_MMP_SOC && MACH_BROWNSTONE + depends on SND_MMP_SOC && MACH_BROWNSTONE && I2C select SND_MMP_SOC_SSPA select MFD_WM8994 select SND_SOC_WM8994 diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 3cde9fb977fa..eff3f9a8b685 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -586,3 +586,6 @@ int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) return 0; } EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove); + +MODULE_DESCRIPTION("QTi LPASS CPU Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index e2ff538a8aa5..07000f53db44 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -61,7 +61,40 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - int ret; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; + struct lpass_data *drvdata = + snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; + int ret, dma_ch, dir = substream->stream; + struct lpass_pcm_data *data; + + data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->i2s_port = cpu_dai->driver->id; + runtime->private_data = data; + + if (v->alloc_dma_channel) + dma_ch = v->alloc_dma_channel(drvdata, dir); + if (dma_ch < 0) + return dma_ch; + + drvdata->substream[dma_ch] = substream; + + ret = regmap_write(drvdata->lpaif_map, + LPAIF_DMACTL_REG(v, dma_ch, dir), 0); + if (ret) { + dev_err(soc_runtime->dev, + "%s() error writing to rdmactl reg: %d\n", + __func__, ret); + return ret; + } + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + data->rdma_ch = dma_ch; + else + data->wrdma_ch = dma_ch; snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); @@ -80,13 +113,40 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) return 0; } +static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_data *drvdata = + snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; + struct lpass_pcm_data *data; + int dma_ch, dir = substream->stream; + + data = runtime->private_data; + v = drvdata->variant; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + dma_ch = data->rdma_ch; + else + dma_ch = data->wrdma_ch; + + drvdata->substream[dma_ch] = NULL; + + if (v->free_dma_channel) + v->free_dma_channel(drvdata, dma_ch); + + return 0; +} + static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); @@ -179,7 +239,8 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; unsigned int reg; int ret; @@ -203,7 +264,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; int ret, ch, dir = substream->stream; @@ -257,7 +319,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; int ret, ch, dir = substream->stream; @@ -333,7 +396,8 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; unsigned int base_addr, curr_addr; int ret, ch, dir = substream->stream; @@ -374,6 +438,7 @@ static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream, static const struct snd_pcm_ops lpass_platform_pcm_ops = { .open = lpass_platform_pcmops_open, + .close = lpass_platform_pcmops_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = lpass_platform_pcmops_hw_params, .hw_free = lpass_platform_pcmops_hw_free, @@ -470,117 +535,45 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) { struct snd_pcm *pcm = soc_runtime->pcm; struct snd_pcm_substream *psubstream, *csubstream; - struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; - struct lpass_data *drvdata = - snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_variant *v = drvdata->variant; int ret = -EINVAL; - struct lpass_pcm_data *data; size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; - data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->i2s_port = cpu_dai->driver->id; - drvdata->private_data = data; - psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; if (psubstream) { - if (v->alloc_dma_channel) - data->rdma_ch = v->alloc_dma_channel(drvdata, - SNDRV_PCM_STREAM_PLAYBACK); - - if (data->rdma_ch < 0) - return data->rdma_ch; - - drvdata->substream[data->rdma_ch] = psubstream; - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, soc_runtime->platform->dev, size, &psubstream->dma_buffer); - if (ret) - goto playback_alloc_err; - - ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, data->rdma_ch), 0); if (ret) { - dev_err(soc_runtime->dev, - "%s() error writing to rdmactl reg: %d\n", - __func__, ret); - goto capture_alloc_err; + dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); + return ret; } } csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; if (csubstream) { - if (v->alloc_dma_channel) - data->wrdma_ch = v->alloc_dma_channel(drvdata, - SNDRV_PCM_STREAM_CAPTURE); - - if (data->wrdma_ch < 0) { - ret = data->wrdma_ch; - goto capture_alloc_err; - } - - drvdata->substream[data->wrdma_ch] = csubstream; - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, soc_runtime->platform->dev, size, &csubstream->dma_buffer); - if (ret) - goto capture_alloc_err; - - ret = regmap_write(drvdata->lpaif_map, - LPAIF_WRDMACTL_REG(v, data->wrdma_ch), 0); if (ret) { - dev_err(soc_runtime->dev, - "%s() error writing to wrdmactl reg: %d\n", - __func__, ret); - goto capture_reg_err; + dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); + if (psubstream) + snd_dma_free_pages(&psubstream->dma_buffer); + return ret; } + } return 0; - -capture_reg_err: - if (csubstream) - snd_dma_free_pages(&csubstream->dma_buffer); - -capture_alloc_err: - if (psubstream) - snd_dma_free_pages(&psubstream->dma_buffer); - - playback_alloc_err: - dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); - - return ret; } static void lpass_platform_pcm_free(struct snd_pcm *pcm) { - struct snd_soc_pcm_runtime *rt; - struct lpass_data *drvdata; - struct lpass_pcm_data *data; - struct lpass_variant *v; struct snd_pcm_substream *substream; - int ch, i; + int i; for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { substream = pcm->streams[i].substream; if (substream) { - rt = substream->private_data; - drvdata = snd_soc_platform_get_drvdata(rt->platform); - data = drvdata->private_data; - - ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ? data->rdma_ch - : data->wrdma_ch; - v = drvdata->variant; - drvdata->substream[ch] = NULL; - if (v->free_dma_channel) - v->free_dma_channel(drvdata, ch); - snd_dma_free_pages(&substream->dma_buffer); substream->dma_buffer.area = NULL; substream->dma_buffer.addr = 0; diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 35b3cea8207d..924971b6ded5 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -59,7 +59,6 @@ struct lpass_data { struct clk *pcnoc_mport_clk; struct clk *pcnoc_sway_clk; - void *private_data; }; /* Vairant data per each SOC */ diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 97d6700b1009..cbc0023c2bc8 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -383,11 +383,6 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err4; } - ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, - s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); - if (ret) - goto err5; - ret = samsung_asoc_dma_platform_register(&pdev->dev, ac97_pdata->dma_filter, NULL, NULL); @@ -396,6 +391,11 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err5; } + ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, + s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); + if (ret) + goto err5; + return 0; err5: free_irq(irq_res->start, NULL); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 7e32cf4581f8..7825bff45ae3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1237,14 +1237,14 @@ static int samsung_i2s_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Unable to get drvdata\n"); return -EFAULT; } - ret = devm_snd_soc_register_component(&sec_dai->pdev->dev, - &samsung_i2s_component, - &sec_dai->i2s_dai_drv, 1); + ret = samsung_asoc_dma_platform_register(&pdev->dev, + sec_dai->filter, "tx-sec", NULL); if (ret != 0) return ret; - return samsung_asoc_dma_platform_register(&pdev->dev, - sec_dai->filter, "tx-sec", NULL); + return devm_snd_soc_register_component(&sec_dai->pdev->dev, + &samsung_i2s_component, + &sec_dai->i2s_dai_drv, 1); } pri_dai = i2s_alloc_dai(pdev, false); @@ -1314,6 +1314,11 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (quirks & QUIRK_PRI_6CHAN) pri_dai->i2s_dai_drv.playback.channels_max = 6; + ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, + NULL, NULL); + if (ret < 0) + goto err_disable_clk; + if (quirks & QUIRK_SEC_DAI) { sec_dai = i2s_alloc_dai(pdev, true); if (!sec_dai) { @@ -1353,10 +1358,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (ret < 0) goto err_free_dai; - ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, - NULL, NULL); - if (ret < 0) - goto err_free_dai; pm_runtime_enable(&pdev->dev); diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 43e367a9acc3..c484985812ed 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -565,24 +565,25 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id]; pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id]; + ret = samsung_asoc_dma_platform_register(&pdev->dev, filter, + NULL, NULL); + if (ret) { + dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); + goto err5; + } + pm_runtime_enable(&pdev->dev); ret = devm_snd_soc_register_component(&pdev->dev, &s3c_pcm_component, &s3c_pcm_dai[pdev->id], 1); if (ret != 0) { dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); - goto err5; - } - - ret = samsung_asoc_dma_platform_register(&pdev->dev, filter, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err5; + goto err6; } return 0; - +err6: + pm_runtime_disable(&pdev->dev); err5: clk_disable_unprepare(pcm->pclk); err4: diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 3e89fbc0c51d..0a4718207e6e 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -168,19 +168,19 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) s3c2412_i2s_pcm_stereo_in.addr = res->start + S3C2412_IISRXD; s3c2412_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; - ret = s3c_i2sv2_register_component(&pdev->dev, -1, - &s3c2412_i2s_component, - &s3c2412_i2s_dai); + ret = samsung_asoc_dma_platform_register(&pdev->dev, + pdata->dma_filter, + NULL, NULL); if (ret) { - pr_err("failed to register the dai\n"); + pr_err("failed to register the DMA: %d\n", ret); return ret; } - ret = samsung_asoc_dma_platform_register(&pdev->dev, - pdata->dma_filter, - NULL, NULL); + ret = s3c_i2sv2_register_component(&pdev->dev, -1, + &s3c2412_i2s_component, + &s3c2412_i2s_dai); if (ret) - pr_err("failed to register the DMA: %d\n", ret); + pr_err("failed to register the dai\n"); return ret; } diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index c78a936a3099..9052f6a7073e 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -474,18 +474,18 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; - ret = devm_snd_soc_register_component(&pdev->dev, - &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); + ret = samsung_asoc_dma_platform_register(&pdev->dev, + pdata->dma_filter, + NULL, NULL); if (ret) { - pr_err("failed to register the dai\n"); + pr_err("failed to register the dma: %d\n", ret); return ret; } - ret = samsung_asoc_dma_platform_register(&pdev->dev, - pdata->dma_filter, - NULL, NULL); + ret = devm_snd_soc_register_component(&pdev->dev, + &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); if (ret) - pr_err("failed to register the dma: %d\n", ret); + pr_err("failed to register the dai\n"); return ret; } diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 26c1fbed4d35..779504f54bc0 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -416,15 +416,6 @@ static int spdif_probe(struct platform_device *pdev) goto err3; } - dev_set_drvdata(&pdev->dev, spdif); - - ret = devm_snd_soc_register_component(&pdev->dev, - &samsung_spdif_component, &samsung_spdif_dai, 1); - if (ret != 0) { - dev_err(&pdev->dev, "fail to register dai\n"); - goto err4; - } - spdif_stereo_out.addr_width = 2; spdif_stereo_out.addr = mem_res->start + DATA_OUTBUF; filter = NULL; @@ -432,7 +423,6 @@ static int spdif_probe(struct platform_device *pdev) spdif_stereo_out.filter_data = spdif_pdata->dma_playback; filter = spdif_pdata->dma_filter; } - spdif->dma_playback = &spdif_stereo_out; ret = samsung_asoc_dma_platform_register(&pdev->dev, filter, @@ -442,6 +432,15 @@ static int spdif_probe(struct platform_device *pdev) goto err4; } + dev_set_drvdata(&pdev->dev, spdif); + + ret = devm_snd_soc_register_component(&pdev->dev, + &samsung_spdif_component, &samsung_spdif_dai, 1); + if (ret != 0) { + dev_err(&pdev->dev, "fail to register dai\n"); + goto err4; + } + return 0; err4: iounmap(spdif->regs); diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 1bc8ebc2528e..ad54d4cf58ad 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -614,7 +614,11 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, iec958->status[3] = ucontrol->value.iec958.status[3]; mutex_unlock(&player->ctrl_lock); - uni_player_set_channel_status(player, NULL); + if (player->substream && player->substream->runtime) + uni_player_set_channel_status(player, + player->substream->runtime); + else + uni_player_set_channel_status(player, NULL); return 0; } diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index e047ec06d538..56ed9472e89f 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -765,11 +765,11 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev) card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) - return NULL; + return ERR_PTR(-ENOMEM); card->dai_link = sun4i_codec_create_link(dev, &card->num_links); if (!card->dai_link) - return NULL; + return ERR_PTR(-ENOMEM); card->dev = dev; card->name = "sun4i-codec"; @@ -829,12 +829,6 @@ static int sun4i_codec_probe(struct platform_device *pdev) return PTR_ERR(scodec->clk_module); } - /* Enable the bus clock */ - if (clk_prepare_enable(scodec->clk_apb)) { - dev_err(&pdev->dev, "Failed to enable the APB clock\n"); - return -EINVAL; - } - scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa", GPIOD_OUT_LOW); if (IS_ERR(scodec->gpio_pa)) { @@ -844,6 +838,12 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } + /* Enable the bus clock */ + if (clk_prepare_enable(scodec->clk_apb)) { + dev_err(&pdev->dev, "Failed to enable the APB clock\n"); + return -EINVAL; + } + /* DMA configuration for TX FIFO */ scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA; scodec->playback_dma_data.maxburst = 4; @@ -876,7 +876,8 @@ static int sun4i_codec_probe(struct platform_device *pdev) } card = sun4i_codec_create_card(&pdev->dev); - if (!card) { + if (IS_ERR(card)) { + ret = PTR_ERR(card); dev_err(&pdev->dev, "Failed to create our card\n"); goto err_unregister_codec; } |