mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-21 22:31:51 +00:00
942 lines
29 KiB
Diff
942 lines
29 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 00fffa3f2310..b0963ca2895d 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 14
|
|
-SUBLEVEL = 32
|
|
+SUBLEVEL = 33
|
|
EXTRAVERSION =
|
|
NAME = Remembering Coco
|
|
|
|
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
|
|
index 6eb97b3a7481..4370933f16cd 100644
|
|
--- a/arch/arm/mm/context.c
|
|
+++ b/arch/arm/mm/context.c
|
|
@@ -144,21 +144,17 @@ static void flush_context(unsigned int cpu)
|
|
/* Update the list of reserved ASIDs and the ASID bitmap. */
|
|
bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
|
|
for_each_possible_cpu(i) {
|
|
- if (i == cpu) {
|
|
- asid = 0;
|
|
- } else {
|
|
- asid = atomic64_xchg(&per_cpu(active_asids, i), 0);
|
|
- /*
|
|
- * If this CPU has already been through a
|
|
- * rollover, but hasn't run another task in
|
|
- * the meantime, we must preserve its reserved
|
|
- * ASID, as this is the only trace we have of
|
|
- * the process it is still running.
|
|
- */
|
|
- if (asid == 0)
|
|
- asid = per_cpu(reserved_asids, i);
|
|
- __set_bit(asid & ~ASID_MASK, asid_map);
|
|
- }
|
|
+ asid = atomic64_xchg(&per_cpu(active_asids, i), 0);
|
|
+ /*
|
|
+ * If this CPU has already been through a
|
|
+ * rollover, but hasn't run another task in
|
|
+ * the meantime, we must preserve its reserved
|
|
+ * ASID, as this is the only trace we have of
|
|
+ * the process it is still running.
|
|
+ */
|
|
+ if (asid == 0)
|
|
+ asid = per_cpu(reserved_asids, i);
|
|
+ __set_bit(asid & ~ASID_MASK, asid_map);
|
|
per_cpu(reserved_asids, i) = asid;
|
|
}
|
|
|
|
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
|
|
index c404fb0df3a6..64bc6c6efc6f 100644
|
|
--- a/arch/arm64/include/asm/cputype.h
|
|
+++ b/arch/arm64/include/asm/cputype.h
|
|
@@ -77,6 +77,8 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void)
|
|
return read_cpuid(CTR_EL0);
|
|
}
|
|
|
|
+void cpuinfo_store_cpu(void);
|
|
+
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif
|
|
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
|
|
index 071c3822442b..1e01d80a1165 100644
|
|
--- a/arch/arm64/kernel/setup.c
|
|
+++ b/arch/arm64/kernel/setup.c
|
|
@@ -41,6 +41,7 @@
|
|
#include <linux/memblock.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/of_platform.h>
|
|
+#include <linux/personality.h>
|
|
|
|
#include <asm/cputype.h>
|
|
#include <asm/elf.h>
|
|
@@ -73,7 +74,6 @@ unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
|
|
#endif
|
|
|
|
static const char *cpu_name;
|
|
-static const char *machine_name;
|
|
phys_addr_t __fdt_pointer __initdata;
|
|
|
|
/*
|
|
@@ -193,6 +193,19 @@ static void __init smp_build_mpidr_hash(void)
|
|
}
|
|
#endif
|
|
|
|
+struct cpuinfo_arm64 {
|
|
+ struct cpu cpu;
|
|
+ u32 reg_midr;
|
|
+};
|
|
+
|
|
+static DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
|
|
+
|
|
+void cpuinfo_store_cpu(void)
|
|
+{
|
|
+ struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
|
|
+ info->reg_midr = read_cpuid_id();
|
|
+}
|
|
+
|
|
static void __init setup_processor(void)
|
|
{
|
|
struct cpu_info *cpu_info;
|
|
@@ -213,6 +226,8 @@ static void __init setup_processor(void)
|
|
sprintf(init_utsname()->machine, ELF_PLATFORM);
|
|
elf_hwcap = 0;
|
|
|
|
+ cpuinfo_store_cpu();
|
|
+
|
|
/*
|
|
* ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks.
|
|
* The blocks we test below represent incremental functionality
|
|
@@ -257,8 +272,6 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
|
|
while (true)
|
|
cpu_relax();
|
|
}
|
|
-
|
|
- machine_name = of_flat_dt_get_machine_name();
|
|
}
|
|
|
|
/*
|
|
@@ -363,14 +376,12 @@ static int __init arm64_device_init(void)
|
|
}
|
|
arch_initcall(arm64_device_init);
|
|
|
|
-static DEFINE_PER_CPU(struct cpu, cpu_data);
|
|
-
|
|
static int __init topology_init(void)
|
|
{
|
|
int i;
|
|
|
|
for_each_possible_cpu(i) {
|
|
- struct cpu *cpu = &per_cpu(cpu_data, i);
|
|
+ struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
|
|
cpu->hotpluggable = 1;
|
|
register_cpu(cpu, i);
|
|
}
|
|
@@ -391,14 +402,41 @@ static const char *hwcap_str[] = {
|
|
NULL
|
|
};
|
|
|
|
+#ifdef CONFIG_COMPAT
|
|
+static const char *compat_hwcap_str[] = {
|
|
+ "swp",
|
|
+ "half",
|
|
+ "thumb",
|
|
+ "26bit",
|
|
+ "fastmult",
|
|
+ "fpa",
|
|
+ "vfp",
|
|
+ "edsp",
|
|
+ "java",
|
|
+ "iwmmxt",
|
|
+ "crunch",
|
|
+ "thumbee",
|
|
+ "neon",
|
|
+ "vfpv3",
|
|
+ "vfpv3d16",
|
|
+ "tls",
|
|
+ "vfpv4",
|
|
+ "idiva",
|
|
+ "idivt",
|
|
+ "vfpd32",
|
|
+ "lpae",
|
|
+ "evtstrm"
|
|
+};
|
|
+#endif /* CONFIG_COMPAT */
|
|
+
|
|
static int c_show(struct seq_file *m, void *v)
|
|
{
|
|
- int i;
|
|
-
|
|
- seq_printf(m, "Processor\t: %s rev %d (%s)\n",
|
|
- cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
|
|
+ int i, j;
|
|
|
|
for_each_online_cpu(i) {
|
|
+ struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
|
|
+ u32 midr = cpuinfo->reg_midr;
|
|
+
|
|
/*
|
|
* glibc reads /proc/cpuinfo to determine the number of
|
|
* online processors, looking for lines beginning with
|
|
@@ -407,24 +445,33 @@ static int c_show(struct seq_file *m, void *v)
|
|
#ifdef CONFIG_SMP
|
|
seq_printf(m, "processor\t: %d\n", i);
|
|
#endif
|
|
- }
|
|
-
|
|
- /* dump out the processor features */
|
|
- seq_puts(m, "Features\t: ");
|
|
-
|
|
- for (i = 0; hwcap_str[i]; i++)
|
|
- if (elf_hwcap & (1 << i))
|
|
- seq_printf(m, "%s ", hwcap_str[i]);
|
|
|
|
- seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
|
|
- seq_printf(m, "CPU architecture: AArch64\n");
|
|
- seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15);
|
|
- seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff);
|
|
- seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
|
|
-
|
|
- seq_puts(m, "\n");
|
|
+ /*
|
|
+ * Dump out the common processor features in a single line.
|
|
+ * Userspace should read the hwcaps with getauxval(AT_HWCAP)
|
|
+ * rather than attempting to parse this, but there's a body of
|
|
+ * software which does already (at least for 32-bit).
|
|
+ */
|
|
+ seq_puts(m, "Features\t:");
|
|
+ if (personality(current->personality) == PER_LINUX32) {
|
|
+#ifdef CONFIG_COMPAT
|
|
+ for (j = 0; compat_hwcap_str[j]; j++)
|
|
+ if (compat_elf_hwcap & (1 << j))
|
|
+ seq_printf(m, " %s", compat_hwcap_str[j]);
|
|
+#endif /* CONFIG_COMPAT */
|
|
+ } else {
|
|
+ for (j = 0; hwcap_str[j]; j++)
|
|
+ if (elf_hwcap & (1 << j))
|
|
+ seq_printf(m, " %s", hwcap_str[j]);
|
|
+ }
|
|
+ seq_puts(m, "\n");
|
|
|
|
- seq_printf(m, "Hardware\t: %s\n", machine_name);
|
|
+ seq_printf(m, "CPU implementer\t: 0x%02x\n", (midr >> 24));
|
|
+ seq_printf(m, "CPU architecture: 8\n");
|
|
+ seq_printf(m, "CPU variant\t: 0x%x\n", ((midr >> 20) & 0xf));
|
|
+ seq_printf(m, "CPU part\t: 0x%03x\n", ((midr >> 4) & 0xfff));
|
|
+ seq_printf(m, "CPU revision\t: %d\n\n", (midr & 0xf));
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
|
|
index 7cfb92a4ab66..7b9542b7bac2 100644
|
|
--- a/arch/arm64/kernel/smp.c
|
|
+++ b/arch/arm64/kernel/smp.c
|
|
@@ -148,6 +148,11 @@ asmlinkage void secondary_start_kernel(void)
|
|
cpu_ops[cpu]->cpu_postboot();
|
|
|
|
/*
|
|
+ * Log the CPU info before it is marked online and might get read.
|
|
+ */
|
|
+ cpuinfo_store_cpu();
|
|
+
|
|
+ /*
|
|
* Enable GIC and timers.
|
|
*/
|
|
notify_cpu_starting(cpu);
|
|
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
|
|
index 67a078ffc464..34467ac8220c 100644
|
|
--- a/arch/mips/cavium-octeon/smp.c
|
|
+++ b/arch/mips/cavium-octeon/smp.c
|
|
@@ -263,9 +263,7 @@ static int octeon_cpu_disable(void)
|
|
|
|
set_cpu_online(cpu, false);
|
|
cpu_clear(cpu, cpu_callin_map);
|
|
- local_irq_disable();
|
|
octeon_fixup_irqs();
|
|
- local_irq_enable();
|
|
|
|
flush_cache_all();
|
|
local_flush_tlb_all();
|
|
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
|
|
index e498f2b3646a..f5598e25e906 100644
|
|
--- a/arch/mips/kernel/irq_cpu.c
|
|
+++ b/arch/mips/kernel/irq_cpu.c
|
|
@@ -56,6 +56,8 @@ static struct irq_chip mips_cpu_irq_controller = {
|
|
.irq_mask_ack = mask_mips_irq,
|
|
.irq_unmask = unmask_mips_irq,
|
|
.irq_eoi = unmask_mips_irq,
|
|
+ .irq_disable = mask_mips_irq,
|
|
+ .irq_enable = unmask_mips_irq,
|
|
};
|
|
|
|
/*
|
|
@@ -92,6 +94,8 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
|
|
.irq_mask_ack = mips_mt_cpu_irq_ack,
|
|
.irq_unmask = unmask_mips_irq,
|
|
.irq_eoi = unmask_mips_irq,
|
|
+ .irq_disable = mask_mips_irq,
|
|
+ .irq_enable = unmask_mips_irq,
|
|
};
|
|
|
|
void __init mips_cpu_irq_init(void)
|
|
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
|
|
index 0a022ee33b2a..18ed11275052 100644
|
|
--- a/arch/mips/kernel/smp.c
|
|
+++ b/arch/mips/kernel/smp.c
|
|
@@ -109,10 +109,10 @@ asmlinkage void start_secondary(void)
|
|
else
|
|
#endif /* CONFIG_MIPS_MT_SMTC */
|
|
cpu_probe();
|
|
- cpu_report();
|
|
per_cpu_trap_init(false);
|
|
mips_clockevent_init();
|
|
mp_ops->init_secondary();
|
|
+ cpu_report();
|
|
|
|
/*
|
|
* XXX parity protection should be folded in here when it's converted
|
|
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
|
index de426887b359..80c22a3ca688 100644
|
|
--- a/arch/x86/kvm/vmx.c
|
|
+++ b/arch/x86/kvm/vmx.c
|
|
@@ -441,6 +441,7 @@ struct vcpu_vmx {
|
|
#endif
|
|
int gs_ldt_reload_needed;
|
|
int fs_reload_needed;
|
|
+ unsigned long vmcs_host_cr4; /* May not match real cr4 */
|
|
} host_state;
|
|
struct {
|
|
int vm86_active;
|
|
@@ -4165,11 +4166,16 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
|
|
u32 low32, high32;
|
|
unsigned long tmpl;
|
|
struct desc_ptr dt;
|
|
+ unsigned long cr4;
|
|
|
|
vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */
|
|
- vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
|
|
vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
|
|
|
|
+ /* Save the most likely value for this task's CR4 in the VMCS. */
|
|
+ cr4 = read_cr4();
|
|
+ vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */
|
|
+ vmx->host_state.vmcs_host_cr4 = cr4;
|
|
+
|
|
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
|
|
#ifdef CONFIG_X86_64
|
|
/*
|
|
@@ -7196,7 +7202,7 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
|
|
static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
|
{
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
- unsigned long debugctlmsr;
|
|
+ unsigned long debugctlmsr, cr4;
|
|
|
|
/* Record the guest's net vcpu time for enforced NMI injections. */
|
|
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
|
|
@@ -7217,6 +7223,12 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
|
if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
|
|
vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
|
|
|
|
+ cr4 = read_cr4();
|
|
+ if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) {
|
|
+ vmcs_writel(HOST_CR4, cr4);
|
|
+ vmx->host_state.vmcs_host_cr4 = cr4;
|
|
+ }
|
|
+
|
|
/* When single-stepping over STI and MOV SS, we must clear the
|
|
* corresponding interruptibility bits in the guest state. Otherwise
|
|
* vmentry fails as it then expects bit 14 (BS) in pending debug
|
|
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
|
|
index 981c2dbd72cc..88f143d9754e 100644
|
|
--- a/arch/x86/pci/common.c
|
|
+++ b/arch/x86/pci/common.c
|
|
@@ -448,6 +448,22 @@ static const struct dmi_system_id pciprobe_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"),
|
|
},
|
|
},
|
|
+ {
|
|
+ .callback = set_scan_all,
|
|
+ .ident = "Stratus/NEC ftServer",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R32"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .callback = set_scan_all,
|
|
+ .ident = "Stratus/NEC ftServer",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R31"),
|
|
+ },
|
|
+ },
|
|
{}
|
|
};
|
|
|
|
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
|
|
index 06f7018c9d95..238f0e627ef3 100644
|
|
--- a/crypto/crc32c.c
|
|
+++ b/crypto/crc32c.c
|
|
@@ -170,3 +170,4 @@ module_exit(crc32c_mod_fini);
|
|
MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
|
|
MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
|
|
MODULE_LICENSE("GPL");
|
|
+MODULE_ALIAS_CRYPTO("crc32c");
|
|
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
|
|
index ccbffd0d7a02..8f42bd724682 100644
|
|
--- a/drivers/gpio/gpiolib.c
|
|
+++ b/drivers/gpio/gpiolib.c
|
|
@@ -911,6 +911,7 @@ int gpiod_export_link(struct device *dev, const char *name,
|
|
if (tdev != NULL) {
|
|
status = sysfs_create_link(&dev->kobj, &tdev->kobj,
|
|
name);
|
|
+ put_device(tdev);
|
|
} else {
|
|
status = -ENODEV;
|
|
}
|
|
@@ -958,7 +959,7 @@ int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
|
|
}
|
|
|
|
status = sysfs_set_active_low(desc, dev, value);
|
|
-
|
|
+ put_device(dev);
|
|
unlock:
|
|
mutex_unlock(&sysfs_lock);
|
|
|
|
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
|
|
index d375322b6cec..0218a9b23b38 100644
|
|
--- a/fs/cifs/file.c
|
|
+++ b/fs/cifs/file.c
|
|
@@ -366,6 +366,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
|
|
struct cifsLockInfo *li, *tmp;
|
|
struct cifs_fid fid;
|
|
struct cifs_pending_open open;
|
|
+ bool oplock_break_cancelled;
|
|
|
|
spin_lock(&cifs_file_list_lock);
|
|
if (--cifs_file->count > 0) {
|
|
@@ -397,7 +398,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
|
|
}
|
|
spin_unlock(&cifs_file_list_lock);
|
|
|
|
- cancel_work_sync(&cifs_file->oplock_break);
|
|
+ oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break);
|
|
|
|
if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
|
|
struct TCP_Server_Info *server = tcon->ses->server;
|
|
@@ -409,6 +410,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
|
|
_free_xid(xid);
|
|
}
|
|
|
|
+ if (oplock_break_cancelled)
|
|
+ cifs_done_oplock_break(cifsi);
|
|
+
|
|
cifs_del_pending_open(&open);
|
|
|
|
/*
|
|
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
|
|
index 2a8b2e15dcc4..589117e9e9be 100644
|
|
--- a/fs/ext4/file.c
|
|
+++ b/fs/ext4/file.c
|
|
@@ -100,7 +100,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
|
|
struct blk_plug plug;
|
|
int unaligned_aio = 0;
|
|
ssize_t ret;
|
|
- int overwrite = 0;
|
|
+ int *overwrite = iocb->private;
|
|
size_t length = iov_length(iov, nr_segs);
|
|
|
|
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
|
|
@@ -118,8 +118,6 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
|
|
mutex_lock(&inode->i_mutex);
|
|
blk_start_plug(&plug);
|
|
|
|
- iocb->private = &overwrite;
|
|
-
|
|
/* check whether we do a DIO overwrite or not */
|
|
if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
|
|
!file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
|
|
@@ -143,7 +141,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
|
|
* So we should check these two conditions.
|
|
*/
|
|
if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
|
|
- overwrite = 1;
|
|
+ *overwrite = 1;
|
|
}
|
|
|
|
ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
|
|
@@ -170,6 +168,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
|
|
{
|
|
struct inode *inode = file_inode(iocb->ki_filp);
|
|
ssize_t ret;
|
|
+ int overwrite = 0;
|
|
|
|
/*
|
|
* If we have encountered a bitmap-format file, the size limit
|
|
@@ -190,6 +189,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
|
|
}
|
|
}
|
|
|
|
+ iocb->private = &overwrite;
|
|
if (unlikely(iocb->ki_filp->f_flags & O_DIRECT))
|
|
ret = ext4_file_dio_write(iocb, iov, nr_segs, pos);
|
|
else
|
|
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
|
|
index 9bc72dec3fa6..b02c202223a6 100644
|
|
--- a/fs/nilfs2/nilfs.h
|
|
+++ b/fs/nilfs2/nilfs.h
|
|
@@ -141,7 +141,6 @@ enum {
|
|
* @ti_save: Backup of journal_info field of task_struct
|
|
* @ti_flags: Flags
|
|
* @ti_count: Nest level
|
|
- * @ti_garbage: List of inode to be put when releasing semaphore
|
|
*/
|
|
struct nilfs_transaction_info {
|
|
u32 ti_magic;
|
|
@@ -150,7 +149,6 @@ struct nilfs_transaction_info {
|
|
one of other filesystems has a bug. */
|
|
unsigned short ti_flags;
|
|
unsigned short ti_count;
|
|
- struct list_head ti_garbage;
|
|
};
|
|
|
|
/* ti_magic */
|
|
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
|
|
index a1a191634abc..5bee81674d53 100644
|
|
--- a/fs/nilfs2/segment.c
|
|
+++ b/fs/nilfs2/segment.c
|
|
@@ -305,7 +305,6 @@ static void nilfs_transaction_lock(struct super_block *sb,
|
|
ti->ti_count = 0;
|
|
ti->ti_save = cur_ti;
|
|
ti->ti_magic = NILFS_TI_MAGIC;
|
|
- INIT_LIST_HEAD(&ti->ti_garbage);
|
|
current->journal_info = ti;
|
|
|
|
for (;;) {
|
|
@@ -332,8 +331,6 @@ static void nilfs_transaction_unlock(struct super_block *sb)
|
|
|
|
up_write(&nilfs->ns_segctor_sem);
|
|
current->journal_info = ti->ti_save;
|
|
- if (!list_empty(&ti->ti_garbage))
|
|
- nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);
|
|
}
|
|
|
|
static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
|
|
@@ -746,6 +743,15 @@ static void nilfs_dispose_list(struct the_nilfs *nilfs,
|
|
}
|
|
}
|
|
|
|
+static void nilfs_iput_work_func(struct work_struct *work)
|
|
+{
|
|
+ struct nilfs_sc_info *sci = container_of(work, struct nilfs_sc_info,
|
|
+ sc_iput_work);
|
|
+ struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
|
|
+
|
|
+ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 0);
|
|
+}
|
|
+
|
|
static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs,
|
|
struct nilfs_root *root)
|
|
{
|
|
@@ -1899,8 +1905,8 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
|
|
static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
|
|
struct the_nilfs *nilfs)
|
|
{
|
|
- struct nilfs_transaction_info *ti = current->journal_info;
|
|
struct nilfs_inode_info *ii, *n;
|
|
+ int defer_iput = false;
|
|
|
|
spin_lock(&nilfs->ns_inode_lock);
|
|
list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
|
|
@@ -1911,9 +1917,24 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
|
|
clear_bit(NILFS_I_BUSY, &ii->i_state);
|
|
brelse(ii->i_bh);
|
|
ii->i_bh = NULL;
|
|
- list_move_tail(&ii->i_dirty, &ti->ti_garbage);
|
|
+ list_del_init(&ii->i_dirty);
|
|
+ if (!ii->vfs_inode.i_nlink) {
|
|
+ /*
|
|
+ * Defer calling iput() to avoid a deadlock
|
|
+ * over I_SYNC flag for inodes with i_nlink == 0
|
|
+ */
|
|
+ list_add_tail(&ii->i_dirty, &sci->sc_iput_queue);
|
|
+ defer_iput = true;
|
|
+ } else {
|
|
+ spin_unlock(&nilfs->ns_inode_lock);
|
|
+ iput(&ii->vfs_inode);
|
|
+ spin_lock(&nilfs->ns_inode_lock);
|
|
+ }
|
|
}
|
|
spin_unlock(&nilfs->ns_inode_lock);
|
|
+
|
|
+ if (defer_iput)
|
|
+ schedule_work(&sci->sc_iput_work);
|
|
}
|
|
|
|
/*
|
|
@@ -2580,6 +2601,8 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
|
|
INIT_LIST_HEAD(&sci->sc_segbufs);
|
|
INIT_LIST_HEAD(&sci->sc_write_logs);
|
|
INIT_LIST_HEAD(&sci->sc_gc_inodes);
|
|
+ INIT_LIST_HEAD(&sci->sc_iput_queue);
|
|
+ INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func);
|
|
init_timer(&sci->sc_timer);
|
|
|
|
sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
|
|
@@ -2606,6 +2629,8 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
|
|
ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
|
|
nilfs_transaction_unlock(sci->sc_super);
|
|
|
|
+ flush_work(&sci->sc_iput_work);
|
|
+
|
|
} while (ret && retrycount-- > 0);
|
|
}
|
|
|
|
@@ -2630,6 +2655,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
|
|
|| sci->sc_seq_request != sci->sc_seq_done);
|
|
spin_unlock(&sci->sc_state_lock);
|
|
|
|
+ if (flush_work(&sci->sc_iput_work))
|
|
+ flag = true;
|
|
+
|
|
if (flag || !nilfs_segctor_confirm(sci))
|
|
nilfs_segctor_write_out(sci);
|
|
|
|
@@ -2639,6 +2667,12 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
|
|
nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
|
|
}
|
|
|
|
+ if (!list_empty(&sci->sc_iput_queue)) {
|
|
+ nilfs_warning(sci->sc_super, __func__,
|
|
+ "iput queue is not empty\n");
|
|
+ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1);
|
|
+ }
|
|
+
|
|
WARN_ON(!list_empty(&sci->sc_segbufs));
|
|
WARN_ON(!list_empty(&sci->sc_write_logs));
|
|
|
|
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
|
|
index 38a1d0013314..a48d6de1e02c 100644
|
|
--- a/fs/nilfs2/segment.h
|
|
+++ b/fs/nilfs2/segment.h
|
|
@@ -26,6 +26,7 @@
|
|
#include <linux/types.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/buffer_head.h>
|
|
+#include <linux/workqueue.h>
|
|
#include <linux/nilfs2_fs.h>
|
|
#include "nilfs.h"
|
|
|
|
@@ -92,6 +93,8 @@ struct nilfs_segsum_pointer {
|
|
* @sc_nblk_inc: Block count of current generation
|
|
* @sc_dirty_files: List of files to be written
|
|
* @sc_gc_inodes: List of GC inodes having blocks to be written
|
|
+ * @sc_iput_queue: list of inodes for which iput should be done
|
|
+ * @sc_iput_work: work struct to defer iput call
|
|
* @sc_freesegs: array of segment numbers to be freed
|
|
* @sc_nfreesegs: number of segments on @sc_freesegs
|
|
* @sc_dsync_inode: inode whose data pages are written for a sync operation
|
|
@@ -135,6 +138,8 @@ struct nilfs_sc_info {
|
|
|
|
struct list_head sc_dirty_files;
|
|
struct list_head sc_gc_inodes;
|
|
+ struct list_head sc_iput_queue;
|
|
+ struct work_struct sc_iput_work;
|
|
|
|
__u64 *sc_freesegs;
|
|
size_t sc_nfreesegs;
|
|
diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h
|
|
index 2609048c1d44..3a34f6edc2d1 100644
|
|
--- a/include/sound/ak4113.h
|
|
+++ b/include/sound/ak4113.h
|
|
@@ -286,7 +286,7 @@ struct ak4113 {
|
|
ak4113_write_t *write;
|
|
ak4113_read_t *read;
|
|
void *private_data;
|
|
- unsigned int init:1;
|
|
+ atomic_t wq_processing;
|
|
spinlock_t lock;
|
|
unsigned char regmap[AK4113_WRITABLE_REGS];
|
|
struct snd_kcontrol *kctls[AK4113_CONTROLS];
|
|
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
|
|
index 52f02a60dba7..069299a88915 100644
|
|
--- a/include/sound/ak4114.h
|
|
+++ b/include/sound/ak4114.h
|
|
@@ -168,7 +168,7 @@ struct ak4114 {
|
|
ak4114_write_t * write;
|
|
ak4114_read_t * read;
|
|
void * private_data;
|
|
- unsigned int init: 1;
|
|
+ atomic_t wq_processing;
|
|
spinlock_t lock;
|
|
unsigned char regmap[6];
|
|
unsigned char txcsb[5];
|
|
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
|
|
index eb89e1807408..60d35ac5d3f1 100644
|
|
--- a/kernel/smpboot.c
|
|
+++ b/kernel/smpboot.c
|
|
@@ -279,6 +279,7 @@ int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread)
|
|
unsigned int cpu;
|
|
int ret = 0;
|
|
|
|
+ get_online_cpus();
|
|
mutex_lock(&smpboot_threads_lock);
|
|
for_each_online_cpu(cpu) {
|
|
ret = __smpboot_create_thread(plug_thread, cpu);
|
|
@@ -291,6 +292,7 @@ int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread)
|
|
list_add(&plug_thread->list, &hotplug_threads);
|
|
out:
|
|
mutex_unlock(&smpboot_threads_lock);
|
|
+ put_online_cpus();
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread);
|
|
diff --git a/lib/checksum.c b/lib/checksum.c
|
|
index 129775eb6de6..8b39e86dbab5 100644
|
|
--- a/lib/checksum.c
|
|
+++ b/lib/checksum.c
|
|
@@ -181,6 +181,15 @@ csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
|
|
EXPORT_SYMBOL(csum_partial_copy);
|
|
|
|
#ifndef csum_tcpudp_nofold
|
|
+static inline u32 from64to32(u64 x)
|
|
+{
|
|
+ /* add up 32-bit and 32-bit for 32+c bit */
|
|
+ x = (x & 0xffffffff) + (x >> 32);
|
|
+ /* add up carry.. */
|
|
+ x = (x & 0xffffffff) + (x >> 32);
|
|
+ return (u32)x;
|
|
+}
|
|
+
|
|
__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
|
|
unsigned short len,
|
|
unsigned short proto,
|
|
@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
|
|
#else
|
|
s += (proto + len) << 8;
|
|
#endif
|
|
- s += (s >> 32);
|
|
- return (__force __wsum)s;
|
|
+ return (__force __wsum)from64to32(s);
|
|
}
|
|
EXPORT_SYMBOL(csum_tcpudp_nofold);
|
|
#endif
|
|
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
|
|
index 2beeabf502c5..9056d22d2880 100644
|
|
--- a/mm/pagewalk.c
|
|
+++ b/mm/pagewalk.c
|
|
@@ -199,7 +199,10 @@ int walk_page_range(unsigned long addr, unsigned long end,
|
|
*/
|
|
if ((vma->vm_start <= addr) &&
|
|
(vma->vm_flags & VM_PFNMAP)) {
|
|
- next = vma->vm_end;
|
|
+ if (walk->pte_hole)
|
|
+ err = walk->pte_hole(addr, next, walk);
|
|
+ if (err)
|
|
+ break;
|
|
pgd = pgd_offset(walk->mm, next);
|
|
continue;
|
|
}
|
|
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
|
|
index db1512ae30cc..f53542b55de6 100644
|
|
--- a/scripts/kconfig/menu.c
|
|
+++ b/scripts/kconfig/menu.c
|
|
@@ -545,7 +545,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
|
{
|
|
int i, j;
|
|
struct menu *submenu[8], *menu, *location = NULL;
|
|
- struct jump_key *jump;
|
|
+ struct jump_key *jump = NULL;
|
|
|
|
str_printf(r, _("Prompt: %s\n"), _(prop->text));
|
|
menu = prop->menu->parent;
|
|
@@ -583,7 +583,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
|
str_printf(r, _(" Location:\n"));
|
|
for (j = 4; --i >= 0; j += 2) {
|
|
menu = submenu[i];
|
|
- if (head && location && menu == location)
|
|
+ if (jump && menu == location)
|
|
jump->offset = strlen(r->s);
|
|
str_printf(r, "%*c-> %s", j, ' ',
|
|
_(menu_get_prompt(menu)));
|
|
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
|
|
index e04e750a77ed..7a9149bb2a38 100644
|
|
--- a/sound/i2c/other/ak4113.c
|
|
+++ b/sound/i2c/other/ak4113.c
|
|
@@ -56,8 +56,7 @@ static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg)
|
|
|
|
static void snd_ak4113_free(struct ak4113 *chip)
|
|
{
|
|
- chip->init = 1; /* don't schedule new work */
|
|
- mb();
|
|
+ atomic_inc(&chip->wq_processing); /* don't schedule new work */
|
|
cancel_delayed_work_sync(&chip->work);
|
|
kfree(chip);
|
|
}
|
|
@@ -89,6 +88,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
|
|
chip->write = write;
|
|
chip->private_data = private_data;
|
|
INIT_DELAYED_WORK(&chip->work, ak4113_stats);
|
|
+ atomic_set(&chip->wq_processing, 0);
|
|
|
|
for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++)
|
|
chip->regmap[reg] = pgm[reg];
|
|
@@ -139,13 +139,11 @@ static void ak4113_init_regs(struct ak4113 *chip)
|
|
|
|
void snd_ak4113_reinit(struct ak4113 *chip)
|
|
{
|
|
- chip->init = 1;
|
|
- mb();
|
|
- flush_delayed_work(&chip->work);
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
+ cancel_delayed_work_sync(&chip->work);
|
|
ak4113_init_regs(chip);
|
|
/* bring up statistics / event queing */
|
|
- chip->init = 0;
|
|
- if (chip->kctls[0])
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
EXPORT_SYMBOL_GPL(snd_ak4113_reinit);
|
|
@@ -632,8 +630,9 @@ static void ak4113_stats(struct work_struct *work)
|
|
{
|
|
struct ak4113 *chip = container_of(work, struct ak4113, work.work);
|
|
|
|
- if (!chip->init)
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
snd_ak4113_check_rate_and_errors(chip, chip->check_flags);
|
|
|
|
- schedule_delayed_work(&chip->work, HZ / 10);
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
+ schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
|
|
index 15ae0250eace..bf515db7c2e1 100644
|
|
--- a/sound/i2c/other/ak4114.c
|
|
+++ b/sound/i2c/other/ak4114.c
|
|
@@ -66,8 +66,7 @@ static void reg_dump(struct ak4114 *ak4114)
|
|
|
|
static void snd_ak4114_free(struct ak4114 *chip)
|
|
{
|
|
- chip->init = 1; /* don't schedule new work */
|
|
- mb();
|
|
+ atomic_inc(&chip->wq_processing); /* don't schedule new work */
|
|
cancel_delayed_work_sync(&chip->work);
|
|
kfree(chip);
|
|
}
|
|
@@ -100,6 +99,7 @@ int snd_ak4114_create(struct snd_card *card,
|
|
chip->write = write;
|
|
chip->private_data = private_data;
|
|
INIT_DELAYED_WORK(&chip->work, ak4114_stats);
|
|
+ atomic_set(&chip->wq_processing, 0);
|
|
|
|
for (reg = 0; reg < 6; reg++)
|
|
chip->regmap[reg] = pgm[reg];
|
|
@@ -152,13 +152,11 @@ static void ak4114_init_regs(struct ak4114 *chip)
|
|
|
|
void snd_ak4114_reinit(struct ak4114 *chip)
|
|
{
|
|
- chip->init = 1;
|
|
- mb();
|
|
- flush_delayed_work(&chip->work);
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
+ cancel_delayed_work_sync(&chip->work);
|
|
ak4114_init_regs(chip);
|
|
/* bring up statistics / event queing */
|
|
- chip->init = 0;
|
|
- if (chip->kctls[0])
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
|
|
@@ -612,10 +610,10 @@ static void ak4114_stats(struct work_struct *work)
|
|
{
|
|
struct ak4114 *chip = container_of(work, struct ak4114, work.work);
|
|
|
|
- if (!chip->init)
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
|
|
-
|
|
- schedule_delayed_work(&chip->work, HZ / 10);
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
+ schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
|
|
EXPORT_SYMBOL(snd_ak4114_create);
|
|
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
|
|
index 1ead3c977a51..f20e703b2a35 100644
|
|
--- a/sound/soc/atmel/atmel_ssc_dai.c
|
|
+++ b/sound/soc/atmel/atmel_ssc_dai.c
|
|
@@ -344,7 +344,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
struct atmel_pcm_dma_params *dma_params;
|
|
int dir, channels, bits;
|
|
u32 tfmr, rfmr, tcmr, rcmr;
|
|
- int start_event;
|
|
int ret;
|
|
|
|
/*
|
|
@@ -451,19 +450,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
* The SSC transmit clock is obtained from the BCLK signal on
|
|
* on the TK line, and the SSC receive clock is
|
|
* generated from the transmit clock.
|
|
- *
|
|
- * For single channel data, one sample is transferred
|
|
- * on the falling edge of the LRC clock.
|
|
- * For two channel data, one sample is
|
|
- * transferred on both edges of the LRC clock.
|
|
*/
|
|
- start_event = ((channels == 1)
|
|
- ? SSC_START_FALLING_RF
|
|
- : SSC_START_EDGE_RF);
|
|
-
|
|
rcmr = SSC_BF(RCMR_PERIOD, 0)
|
|
| SSC_BF(RCMR_STTDLY, START_DELAY)
|
|
- | SSC_BF(RCMR_START, start_event)
|
|
+ | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
|
|
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
|
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
|
| SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
|
|
@@ -471,14 +461,14 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
|
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
|
|
| SSC_BF(RFMR_FSLEN, 0)
|
|
- | SSC_BF(RFMR_DATNB, 0)
|
|
+ | SSC_BF(RFMR_DATNB, (channels - 1))
|
|
| SSC_BIT(RFMR_MSBF)
|
|
| SSC_BF(RFMR_LOOP, 0)
|
|
| SSC_BF(RFMR_DATLEN, (bits - 1));
|
|
|
|
tcmr = SSC_BF(TCMR_PERIOD, 0)
|
|
| SSC_BF(TCMR_STTDLY, START_DELAY)
|
|
- | SSC_BF(TCMR_START, start_event)
|
|
+ | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
|
|
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
|
|
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
|
|
| SSC_BF(TCMR_CKS, SSC_CKS_PIN);
|
|
@@ -487,7 +477,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
| SSC_BF(TFMR_FSDEN, 0)
|
|
| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
|
|
| SSC_BF(TFMR_FSLEN, 0)
|
|
- | SSC_BF(TFMR_DATNB, 0)
|
|
+ | SSC_BF(TFMR_DATNB, (channels - 1))
|
|
| SSC_BIT(TFMR_MSBF)
|
|
| SSC_BF(TFMR_DATDEF, 0)
|
|
| SSC_BF(TFMR_DATLEN, (bits - 1));
|
|
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
|
|
index 12528e9ac4c2..715589ff0eda 100644
|
|
--- a/sound/soc/codecs/sgtl5000.c
|
|
+++ b/sound/soc/codecs/sgtl5000.c
|
|
@@ -1521,6 +1521,9 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ /* Need 8 clocks before I2C accesses */
|
|
+ udelay(1);
|
|
+
|
|
/* read chip information */
|
|
ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®);
|
|
if (ret)
|