diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst index 469d115a95f1..a901def730d9 100644 --- a/Documentation/dev-tools/kselftest.rst +++ b/Documentation/dev-tools/kselftest.rst @@ -125,32 +125,41 @@ Note that some tests will require root privileges. Install selftests ================= -You can use the kselftest_install.sh tool to install selftests in the -default location, which is tools/testing/selftests/kselftest, or in a -user specified location. +You can use the "install" target of "make" (which calls the `kselftest_install.sh` +tool) to install selftests in the default location (`tools/testing/selftests/kselftest_install`), +or in a user specified location via the `INSTALL_PATH` "make" variable. To install selftests in default location:: - $ cd tools/testing/selftests - $ ./kselftest_install.sh + $ make -C tools/testing/selftests install To install selftests in a user specified location:: - $ cd tools/testing/selftests - $ ./kselftest_install.sh install_dir + $ make -C tools/testing/selftests install INSTALL_PATH=/some/other/path Running installed selftests =========================== -Kselftest install as well as the Kselftest tarball provide a script -named "run_kselftest.sh" to run the tests. +Found in the install directory, as well as in the Kselftest tarball, +is a script named `run_kselftest.sh` to run the tests. You can simply do the following to run the installed Kselftests. Please note some tests will require root privileges:: - $ cd kselftest + $ cd kselftest_install $ ./run_kselftest.sh +To see the list of available tests, the `-l` option can be used:: + + $ ./run_kselftest.sh -l + +The `-c` option can be used to run all the tests from a test collection, or +the `-t` option for specific single tests. Either can be used multiple times:: + + $ ./run_kselftest.sh -c bpf -c seccomp -t timers:posix_timers -t timer:nanosleep + +For other features see the script usage output, seen with the `-h` option. + Packaging selftests =================== @@ -160,9 +169,9 @@ different system. To package selftests, run:: $ make -C tools/testing/selftests gen_tar This generates a tarball in the `INSTALL_PATH/kselftest-packages` directory. By -default, `.gz` format is used. The tar format can be overridden by specifying -a `FORMAT` make variable. Any value recognized by `tar's auto-compress`_ option -is supported, such as:: +default, `.gz` format is used. The tar compression format can be overridden by +specifying a `FORMAT` make variable. Any value recognized by `tar's auto-compress`_ +option is supported, such as:: $ make -C tools/testing/selftests gen_tar FORMAT=.xz diff --git a/MAINTAINERS b/MAINTAINERS index 8398c6ca01b8..c04d3214ff0e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4415,6 +4415,7 @@ S: Supported T: git git://git.infradead.org/users/hch/configfs.git F: fs/configfs/ F: include/linux/configfs.h +F: samples/configfs/ CONSOLE SUBSYSTEM M: Greg Kroah-Hartman @@ -11708,7 +11709,7 @@ S: Odd Fixes T: git git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git F: arch/arm/boot/dts/mmp* F: arch/arm/mach-mmp/ -F: linux/soc/mmp/ +F: include/linux/soc/mmp/ MMP USB PHY DRIVERS R: Lubomir Rintel diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index d9a50f7a666c..a1167ada29b6 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -375,5 +375,6 @@ config KEXEC_FILE endmenu +source "drivers/firmware/Kconfig" source "drivers/parisc/Kconfig" diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index 61bac8ff8f22..3cbcfad5f724 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -52,10 +52,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_IDE=y -CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_NS87415=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y @@ -65,6 +61,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_ZALON=y CONFIG_SCSI_DH=y CONFIG_ATA=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_NS87415=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig index 59561e04e659..7e2d7026285e 100644 --- a/arch/parisc/configs/generic-64bit_defconfig +++ b/arch/parisc/configs/generic-64bit_defconfig @@ -58,11 +58,6 @@ CONFIG_PCI_IOV=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_BLK_DEV_LOOP=y -CONFIG_IDE=y -CONFIG_IDE_GD=m -CONFIG_IDE_GD_ATAPI=y -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_NS87415=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y @@ -76,6 +71,7 @@ CONFIG_SCSI_ZALON=y CONFIG_SCSI_QLA_ISCSI=m CONFIG_SCSI_DH=y CONFIG_ATA=y +CONFIG_PATA_NS87415=y CONFIG_PATA_SIL680=y CONFIG_ATA_GENERIC=y CONFIG_MD=y diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h index 640d46edf32e..c705decf2bed 100644 --- a/arch/parisc/include/asm/barrier.h +++ b/arch/parisc/include/asm/barrier.h @@ -2,11 +2,15 @@ #ifndef __ASM_BARRIER_H #define __ASM_BARRIER_H +#include + #ifndef __ASSEMBLY__ /* The synchronize caches instruction executes as a nop on systems in which all memory references are performed in order. */ -#define synchronize_caches() __asm__ __volatile__ ("sync" : : : "memory") +#define synchronize_caches() asm volatile("sync" \ + ALTERNATIVE(ALT_COND_NO_SMP, INSN_NOP) \ + : : : "memory") #if defined(CONFIG_SMP) #define mb() do { synchronize_caches(); } while (0) diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index 068958575871..cf5ee9b0b393 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -14,22 +14,22 @@ extern void __xchg_called_with_bad_pointer(void); /* __xchg32/64 defined in arch/parisc/lib/bitops.c */ -extern unsigned long __xchg8(char, char *); -extern unsigned long __xchg32(int, int *); +extern unsigned long __xchg8(char, volatile char *); +extern unsigned long __xchg32(int, volatile int *); #ifdef CONFIG_64BIT -extern unsigned long __xchg64(unsigned long, unsigned long *); +extern unsigned long __xchg64(unsigned long, volatile unsigned long *); #endif /* optimizer better get rid of switch since size is a constant */ static inline unsigned long -__xchg(unsigned long x, __volatile__ void *ptr, int size) +__xchg(unsigned long x, volatile void *ptr, int size) { switch (size) { #ifdef CONFIG_64BIT - case 8: return __xchg64(x, (unsigned long *) ptr); + case 8: return __xchg64(x, (volatile unsigned long *) ptr); #endif - case 4: return __xchg32((int) x, (int *) ptr); - case 1: return __xchg8((char) x, (char *) ptr); + case 4: return __xchg32((int) x, (volatile int *) ptr); + case 1: return __xchg8((char) x, (volatile char *) ptr); } __xchg_called_with_bad_pointer(); return x; diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h index c459f656c8c3..fceb9cf02fb3 100644 --- a/arch/parisc/include/asm/futex.h +++ b/arch/parisc/include/asm/futex.h @@ -16,7 +16,7 @@ static inline void _futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags) { extern u32 lws_lock_start[]; - long index = ((long)uaddr & 0xf0) >> 2; + long index = ((long)uaddr & 0x3f8) >> 1; arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index]; local_irq_save(*flags); arch_spin_lock(s); @@ -26,7 +26,7 @@ static inline void _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags) { extern u32 lws_lock_start[]; - long index = ((long)uaddr & 0xf0) >> 2; + long index = ((long)uaddr & 0x3f8) >> 1; arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index]; arch_spin_unlock(s); local_irq_restore(*flags); diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h index 79feff1b0721..33500c9f6e5e 100644 --- a/arch/parisc/include/asm/socket.h +++ b/arch/parisc/include/asm/socket.h @@ -4,8 +4,8 @@ #include -/* O_NONBLOCK clashes with the bits used for socket types. Therefore we - * have to define SOCK_NONBLOCK to a different value here. +/* O_NONBLOCK clashed with the bits used for socket types. Therefore we + * had to define SOCK_NONBLOCK to a different value here. */ #define SOCK_NONBLOCK 0x40000000 diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h index 51b6c47f802f..fa5ee8a45dbd 100644 --- a/arch/parisc/include/asm/spinlock.h +++ b/arch/parisc/include/asm/spinlock.h @@ -10,13 +10,21 @@ static inline int arch_spin_is_locked(arch_spinlock_t *x) { volatile unsigned int *a = __ldcw_align(x); - return *a == 0; + return READ_ONCE(*a) == 0; } -#define arch_spin_lock(lock) arch_spin_lock_flags(lock, 0) +static inline void arch_spin_lock(arch_spinlock_t *x) +{ + volatile unsigned int *a; + + a = __ldcw_align(x); + while (__ldcw(a) == 0) + while (*a == 0) + continue; +} static inline void arch_spin_lock_flags(arch_spinlock_t *x, - unsigned long flags) + unsigned long flags) { volatile unsigned int *a; @@ -25,10 +33,8 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x, while (*a == 0) if (flags & PSW_SM_I) { local_irq_enable(); - cpu_relax(); local_irq_disable(); - } else - cpu_relax(); + } } #define arch_spin_lock_flags arch_spin_lock_flags @@ -44,12 +50,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *x) static inline int arch_spin_trylock(arch_spinlock_t *x) { volatile unsigned int *a; - int ret; a = __ldcw_align(x); - ret = __ldcw(a) != 0; - - return ret; + return __ldcw(a) != 0; } /* diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h index 03ce20e5ad7d..03dee816cb13 100644 --- a/arch/parisc/include/uapi/asm/fcntl.h +++ b/arch/parisc/include/uapi/asm/fcntl.h @@ -3,22 +3,19 @@ #define _PARISC_FCNTL_H #define O_APPEND 000000010 -#define O_BLKSEEK 000000100 /* HPUX only */ #define O_CREAT 000000400 /* not fcntl */ #define O_EXCL 000002000 /* not fcntl */ #define O_LARGEFILE 000004000 #define __O_SYNC 000100000 #define O_SYNC (__O_SYNC|O_DSYNC) -#define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */ +#define O_NONBLOCK 000200000 #define O_NOCTTY 000400000 /* not fcntl */ -#define O_DSYNC 001000000 /* HPUX only */ -#define O_RSYNC 002000000 /* HPUX only */ +#define O_DSYNC 001000000 #define O_NOATIME 004000000 #define O_CLOEXEC 010000000 /* set close_on_exec */ #define O_DIRECTORY 000010000 /* must be a directory */ #define O_NOFOLLOW 000000200 /* don't follow links */ -#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */ #define O_PATH 020000000 #define __O_TMPFILE 040000000 diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 6fd8871e4081..ab78cba446ed 100644 --- a/arch/parisc/include/uapi/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h @@ -25,6 +25,7 @@ #define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */ #define MAP_HUGETLB 0x80000 /* create a huge page mapping */ #define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */ +#define MAP_UNINITIALIZED 0 /* uninitialized anonymous mmap */ #define MS_SYNC 1 /* synchronous memory sync */ #define MS_ASYNC 2 /* sync memory asynchronously */ diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h index d38563a394f2..e605197b462c 100644 --- a/arch/parisc/include/uapi/asm/signal.h +++ b/arch/parisc/include/uapi/asm/signal.h @@ -35,11 +35,11 @@ #define SIGURG 29 #define SIGXFSZ 30 #define SIGUNUSED 31 -#define SIGSYS 31 /* Linux doesn't use this */ +#define SIGSYS 31 /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX _NSIG /* it's 44 under HP/UX */ +#define SIGRTMAX _NSIG /* * SA_FLAGS values: @@ -61,7 +61,6 @@ #define SA_NODEFER 0x00000020 #define SA_RESTART 0x00000040 #define SA_NOCLDWAIT 0x00000080 -#define _SA_SIGGFAULT 0x00000100 /* HPUX */ #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh index 6f68784fea25..056d588befdd 100644 --- a/arch/parisc/install.sh +++ b/arch/parisc/install.sh @@ -43,7 +43,7 @@ fi # Default install -if [ "$(basename $2)" = "zImage" ]; then +if [ "$(basename $2)" = "vmlinuz" ]; then # Compressed install echo "Installing compressed kernel" base=vmlinuz diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index b5e1d9f1b440..86a1a63563fd 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -383,12 +383,12 @@ EXPORT_SYMBOL(flush_kernel_icache_range_asm); static unsigned long parisc_cache_flush_threshold __ro_after_init = FLUSH_THRESHOLD; #define FLUSH_TLB_THRESHOLD (16*1024) /* 16 KiB minimum TLB threshold */ -static unsigned long parisc_tlb_flush_threshold __ro_after_init = FLUSH_TLB_THRESHOLD; +static unsigned long parisc_tlb_flush_threshold __ro_after_init = ~0UL; void __init parisc_setup_cache_timing(void) { unsigned long rangetime, alltime; - unsigned long size, start; + unsigned long size; unsigned long threshold; alltime = mfctl(16); @@ -422,14 +422,9 @@ void __init parisc_setup_cache_timing(void) goto set_tlb_threshold; } - size = 0; - start = (unsigned long) _text; + size = (unsigned long)_end - (unsigned long)_text; rangetime = mfctl(16); - while (start < (unsigned long) _end) { - flush_tlb_kernel_range(start, start + PAGE_SIZE); - start += PAGE_SIZE; - size += PAGE_SIZE; - } + flush_tlb_kernel_range((unsigned long)_text, (unsigned long)_end); rangetime = mfctl(16) - rangetime; alltime = mfctl(16); @@ -444,8 +439,11 @@ void __init parisc_setup_cache_timing(void) threshold/1024); set_tlb_threshold: - if (threshold > parisc_tlb_flush_threshold) + if (threshold > FLUSH_TLB_THRESHOLD) parisc_tlb_flush_threshold = threshold; + else + parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; + printk(KERN_INFO "TLB flush threshold set to %lu KiB\n", parisc_tlb_flush_threshold/1024); } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 519f9056fd00..f6f28e41bb5e 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -899,20 +899,20 @@ intr_check_sig: * Only do signals if we are returning to user space */ LDREG PT_IASQ0(%r16), %r20 - cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */ + cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* forward */ LDREG PT_IASQ1(%r16), %r20 - cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */ - - /* NOTE: We need to enable interrupts if we have to deliver - * signals. We used to do this earlier but it caused kernel - * stack overflows. */ - ssm PSW_SM_I, %r0 + cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* forward */ copy %r0, %r25 /* long in_syscall = 0 */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif + /* NOTE: We need to enable interrupts if we have to deliver + * signals. We used to do this earlier but it caused kernel + * stack overflows. */ + ssm PSW_SM_I, %r0 + BL do_notify_resume,%r2 copy %r16, %r26 /* struct pt_regs *regs */ diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 9298f2285510..7ab2f2a54400 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -641,4 +642,33 @@ void __init do_device_inventory(void) if (pa_serialize_tlb_flushes) pr_info("Merced bus found: Enable PxTLB serialization.\n"); #endif + +#if defined(CONFIG_FW_CFG_SYSFS) + if (running_on_qemu) { + struct resource res[3] = {0,}; + unsigned int base; + + base = ((unsigned long long) PAGE0->pad0[2] << 32) + | PAGE0->pad0[3]; /* SeaBIOS stored it here */ + + res[0].name = "fw_cfg"; + res[0].start = base; + res[0].end = base + 8 - 1; + res[0].flags = IORESOURCE_MEM; + + res[1].name = "ctrl"; + res[1].start = 0; + res[1].flags = IORESOURCE_REG; + + res[2].name = "data"; + res[2].start = 4; + res[2].flags = IORESOURCE_REG; + + if (base) { + pr_info("Found qemu fw_cfg interface at %#08x\n", base); + platform_device_register_simple("fw_cfg", + PLATFORM_DEVID_NONE, res, 3); + } + } +#endif } diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 6271139d2213..10227f667c8a 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -173,9 +173,12 @@ ipi_interrupt(int irq, void *dev_id) this_cpu, which); return IRQ_NONE; } /* Switch */ - /* let in any pending interrupts */ - local_irq_enable(); - local_irq_disable(); + + /* before doing more, let in any pending interrupts */ + if (ops) { + local_irq_enable(); + local_irq_disable(); + } } /* while (ops) */ } return IRQ_HANDLED; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 3ad61a177f5b..322503780db6 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -571,8 +571,8 @@ lws_compare_and_swap: ldil L%lws_lock_start, %r20 ldo R%lws_lock_start(%r20), %r28 - /* Extract four bits from r26 and hash lock (Bits 4-7) */ - extru %r26, 27, 4, %r20 + /* Extract eight bits from r26 and hash lock (Bits 3-11) */ + extru %r26, 28, 8, %r20 /* Find lock to use, the hash is either one of 0 to 15, multiplied by 16 (keep it 16-byte aligned) @@ -761,8 +761,8 @@ cas2_lock_start: ldil L%lws_lock_start, %r20 ldo R%lws_lock_start(%r20), %r28 - /* Extract four bits from r26 and hash lock (Bits 4-7) */ - extru %r26, 27, 4, %r20 + /* Extract eight bits from r26 and hash lock (Bits 3-11) */ + extru %r26, 28, 8, %r20 /* Find lock to use, the hash is either one of 0 to 15, multiplied by 16 (keep it 16-byte aligned) @@ -950,7 +950,7 @@ END(sys_call_table64) .align L1_CACHE_BYTES ENTRY(lws_lock_start) /* lws locks */ - .rept 16 + .rept 256 /* Keep locks aligned at 16-bytes */ .word 1 .word 0 diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c index 2e4d1f05a926..9ac683bf6ae7 100644 --- a/arch/parisc/lib/bitops.c +++ b/arch/parisc/lib/bitops.c @@ -18,7 +18,7 @@ arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { #endif #ifdef CONFIG_64BIT -unsigned long __xchg64(unsigned long x, unsigned long *ptr) +unsigned long __xchg64(unsigned long x, volatile unsigned long *ptr) { unsigned long temp, flags; @@ -30,7 +30,7 @@ unsigned long __xchg64(unsigned long x, unsigned long *ptr) } #endif -unsigned long __xchg32(int x, int *ptr) +unsigned long __xchg32(int x, volatile int *ptr) { unsigned long flags; long temp; @@ -43,7 +43,7 @@ unsigned long __xchg32(int x, int *ptr) } -unsigned long __xchg8(char x, char *ptr) +unsigned long __xchg8(char x, volatile char *ptr) { unsigned long flags; long temp; diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c index ce400417d54e..f03adb1999e7 100644 --- a/arch/parisc/lib/iomap.c +++ b/arch/parisc/lib/iomap.c @@ -346,6 +346,16 @@ u64 ioread64be(const void __iomem *addr) return *((u64 *)addr); } +u64 ioread64_hi_lo(const void __iomem *addr) +{ + u32 low, high; + + high = ioread32(addr + sizeof(u32)); + low = ioread32(addr); + + return low + ((u64)high << 32); +} + void iowrite8(u8 datum, void __iomem *addr) { if (unlikely(INDIRECT_ADDR(addr))) { @@ -409,6 +419,12 @@ void iowrite64be(u64 datum, void __iomem *addr) } } +void iowrite64_hi_lo(u64 val, void __iomem *addr) +{ + iowrite32(val >> 32, addr + sizeof(u32)); + iowrite32(val, addr); +} + /* Repeating interfaces */ void ioread8_rep(const void __iomem *addr, void *dst, unsigned long count) @@ -511,6 +527,7 @@ EXPORT_SYMBOL(ioread32); EXPORT_SYMBOL(ioread32be); EXPORT_SYMBOL(ioread64); EXPORT_SYMBOL(ioread64be); +EXPORT_SYMBOL(ioread64_hi_lo); EXPORT_SYMBOL(iowrite8); EXPORT_SYMBOL(iowrite16); EXPORT_SYMBOL(iowrite16be); @@ -518,6 +535,7 @@ EXPORT_SYMBOL(iowrite32); EXPORT_SYMBOL(iowrite32be); EXPORT_SYMBOL(iowrite64); EXPORT_SYMBOL(iowrite64be); +EXPORT_SYMBOL(iowrite64_hi_lo); EXPORT_SYMBOL(ioread8_rep); EXPORT_SYMBOL(ioread16_rep); EXPORT_SYMBOL(ioread32_rep); diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 4f77b8f22e54..ffc289992d1b 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -54,6 +54,7 @@ typedef int (*hyperv_fill_flush_list_func)( #define hv_enable_vdso_clocksource() \ vclocks_set_used(VDSO_CLOCKMODE_HVCLOCK); #define hv_get_raw_timer() rdtsc_ordered() +#define hv_get_vector() HYPERVISOR_CALLBACK_VECTOR /* * Reference to pv_ops must be inline so objtool diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 9834a43cd0fa..05ef1f4550cb 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -55,9 +55,14 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback) set_irq_regs(old_regs); } -void hv_setup_vmbus_irq(void (*handler)(void)) +int hv_setup_vmbus_irq(int irq, void (*handler)(void)) { + /* + * The 'irq' argument is ignored on x86/x64 because a hard-coded + * interrupt vector is used for Hyper-V interrupts. + */ vmbus_handler = handler; + return 0; } void hv_remove_vmbus_irq(void) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index d8a29dc5a284..b73d775831f1 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -523,7 +523,7 @@ config MEMMAP_CACHEATTR 2: cache bypass, 4: WB cached, f: illegal. - For ful MMU: + For full MMU: bit 0: executable, bit 1: writable, bits 2..3: diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 05280184c701..24d04373f4d0 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -186,7 +186,7 @@ config RASPBERRYPI_FIRMWARE config FW_CFG_SYSFS tristate "QEMU fw_cfg device support in sysfs" - depends on SYSFS && (ARM || ARM64 || PPC_PMAC || SPARC || X86) + depends on SYSFS && (ARM || ARM64 || PARISC || PPC_PMAC || SPARC || X86) depends on HAS_IOPORT_MAP default n help diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 6945c3c96637..0078260fbabe 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -215,6 +215,9 @@ static void fw_cfg_io_cleanup(void) # define FW_CFG_CTRL_OFF 0x08 # define FW_CFG_DATA_OFF 0x00 # define FW_CFG_DMA_OFF 0x10 +# elif defined(CONFIG_PARISC) /* parisc */ +# define FW_CFG_CTRL_OFF 0x00 +# define FW_CFG_DATA_OFF 0x04 # elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */ # define FW_CFG_CTRL_OFF 0x00 # define FW_CFG_DATA_OFF 0x02 diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index a68559cc5a0e..520c2c6105bf 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -397,6 +397,15 @@ config HID_GOOGLE_HAMMER help Say Y here if you have a Google Hammer device. +config HID_VIVALDI + tristate "Vivaldi Keyboard" + depends on HID + help + Say Y here if you want to enable support for Vivaldi keyboards. + + Vivaldi keyboards use a vendor-specific (Google) HID usage to report + how the keys in the top row are physically ordered. + config HID_GT683R tristate "MSI GT68xR LED support" depends on LEDS_CLASS && USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index d0cc21b38251..3a3a7b3ce7c8 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o obj-$(CONFIG_HID_GFRM) += hid-gfrm.o obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o obj-$(CONFIG_HID_GOOGLE_HAMMER) += hid-google-hammer.o +obj-$(CONFIG_HID_VIVALDI) += hid-vivaldi.o obj-$(CONFIG_HID_GT683R) += hid-gt683r.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c index a9c2de95c5e2..3feaece13ade 100644 --- a/drivers/hid/hid-alps.c +++ b/drivers/hid/hid-alps.c @@ -526,7 +526,7 @@ static int u1_init(struct hid_device *hdev, struct alps_dev *pri_data) ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y, &sen_line_num_y, 0, true); - if (ret < 0) { + if (ret < 0) { dev_err(&hdev->dev, "failed U1_NUM_SENS_Y (%d)\n", ret); goto exit; } diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index e82f604d33e9..6b8f0d004d34 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -503,6 +503,8 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), .driver_data = APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), + .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS), .driver_data = APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d2ecc9c45255..56172fe6995c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -814,6 +814,13 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) if ((parser->global.usage_page << 16) >= HID_UP_MSVENDOR) parser->scan_flags |= HID_SCAN_FLAG_VENDOR_SPECIFIC; + + if ((parser->global.usage_page << 16) == HID_UP_GOOGLEVENDOR) + for (i = 0; i < parser->local.usage_index; i++) + if (parser->local.usage[i] == + (HID_UP_GOOGLEVENDOR | 0x0001)) + parser->device->group = + HID_GROUP_VIVALDI; } static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) @@ -920,7 +927,7 @@ static int hid_scan_report(struct hid_device *hid) /** * hid_parse_report - parse device report * - * @device: hid device + * @hid: hid device * @start: report start * @size: report size * @@ -945,7 +952,7 @@ static const char * const hid_report_names[] = { /** * hid_validate_values - validate existing device report's value indexes * - * @device: hid device + * @hid: hid device * @type: which report type to examine * @id: which report ID to examine (0 for first) * @field_index: which report field to examine @@ -1444,7 +1451,7 @@ static int search(__s32 *array, __s32 value, unsigned n) * hid_match_report - check if driver's raw_event should be called * * @hid: hid device - * @report_type: type to match against + * @report: hid report to match against * * compare hid->driver->report_table->report_type to report->type */ @@ -2120,7 +2127,7 @@ struct hid_dynid { /** * store_new_id - add a new HID device ID to this driver and re-probe devices - * @driver: target device driver + * @drv: target device driver * @buf: buffer for scanning device ID data * @count: input size * diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index f64517bc33e2..21e15627a461 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -1235,6 +1235,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) struct cp2112_device *dev; u8 buf[3]; struct cp2112_smbus_config_report config; + struct gpio_irq_chip *girq; int ret; dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); @@ -1338,6 +1339,15 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) dev->gc.can_sleep = 1; dev->gc.parent = &hdev->dev; + girq = &dev->gc.irq; + girq->chip = &cp2112_gpio_irqchip; + /* The event comes from the outside so no parent handler */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + ret = gpiochip_add_data(&dev->gc, dev); if (ret < 0) { hid_err(hdev, "error registering gpio chip\n"); @@ -1353,17 +1363,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) chmod_sysfs_attrs(hdev); hid_hw_power(hdev, PM_HINT_NORMAL); - ret = gpiochip_irqchip_add(&dev->gc, &cp2112_gpio_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev->gc.parent, "failed to add IRQ chip\n"); - goto err_sysfs_remove; - } - return ret; -err_sysfs_remove: - sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); err_gpiochip_remove: gpiochip_remove(&dev->gc); err_free_i2c: diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 9453147d020d..d7eaf9100370 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -1101,11 +1101,6 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, set_current_state(TASK_INTERRUPTIBLE); while (kfifo_is_empty(&list->hid_debug_fifo)) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -1122,6 +1117,11 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, goto out; } + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + /* allow O_NONBLOCK from other threads */ mutex_unlock(&list->read_mutex); schedule(); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 73b4244e5358..17eb9775db17 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -727,6 +727,8 @@ #define USB_DEVICE_ID_LENOVO_TP10UBKBD 0x6062 #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067 #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 +#define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 +#define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019 #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e @@ -1126,6 +1128,7 @@ #define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968 #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 +#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f5 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7 #define USB_VENDOR_ID_TEXAS_INSTRUMENTS 0x2047 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 88e19996427e..9770db624bfa 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -797,7 +797,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x3b: /* Battery Strength */ hidinput_setup_battery(device, HID_INPUT_REPORT, field); usage->type = EV_PWR; - goto ignore; + return; case 0x3c: /* Invert */ map_key_clear(BTN_TOOL_RUBBER); @@ -1059,7 +1059,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_DC_BATTERYSTRENGTH: hidinput_setup_battery(device, HID_INPUT_REPORT, field); usage->type = EV_PWR; - goto ignore; + return; } goto unknown; diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c index 6c55682c5974..044a93f3c117 100644 --- a/drivers/hid/hid-ite.c +++ b/drivers/hid/hid-ite.c @@ -44,6 +44,10 @@ static const struct hid_device_id ite_devices[] = { { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) }, + /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_SYNAPTICS, + USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003) }, { } }; MODULE_DEVICE_TABLE(hid, ite_devices); diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 38ee25a813b9..72fb6e54a50a 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -820,7 +820,7 @@ static void logi_dj_recv_queue_unknown_work(struct dj_receiver_dev *djrcv_dev) { struct dj_workitem workitem = { .type = WORKITEM_TYPE_UNKNOWN }; - /* Rate limit queries done because of unhandeled reports to 2/sec */ + /* Rate limit queries done because of unhandled reports to 2/sec */ if (time_before(jiffies, djrcv_dev->last_query + HZ / 2)) return; diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index e3152155c4b8..d670bcd57bde 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1973,6 +1973,18 @@ static const struct hid_device_id mt_devices[] = { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC, USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) }, + /* Lenovo X1 TAB Gen 2 */ + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, + HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LENOVO, + USB_DEVICE_ID_LENOVO_X1_TAB) }, + + /* Lenovo X1 TAB Gen 3 */ + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, + HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LENOVO, + USB_DEVICE_ID_LENOVO_X1_TAB3) }, + /* MosArt panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_ASUS, diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 2ff4c8e366ff..1ca64481145e 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -294,31 +294,40 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0, difference, old_profile; + struct kone_settings *settings = (struct kone_settings *)buf; /* I need to get my data in one piece */ if (off != 0 || count != sizeof(struct kone_settings)) return -EINVAL; mutex_lock(&kone->kone_lock); - difference = memcmp(buf, &kone->settings, sizeof(struct kone_settings)); + difference = memcmp(settings, &kone->settings, + sizeof(struct kone_settings)); if (difference) { - retval = kone_set_settings(usb_dev, - (struct kone_settings const *)buf); - if (retval) { - mutex_unlock(&kone->kone_lock); - return retval; + if (settings->startup_profile < 1 || + settings->startup_profile > 5) { + retval = -EINVAL; + goto unlock; } + retval = kone_set_settings(usb_dev, settings); + if (retval) + goto unlock; + old_profile = kone->settings.startup_profile; - memcpy(&kone->settings, buf, sizeof(struct kone_settings)); + memcpy(&kone->settings, settings, sizeof(struct kone_settings)); kone_profile_activated(kone, kone->settings.startup_profile); if (kone->settings.startup_profile != old_profile) kone_profile_report(kone, kone->settings.startup_profile); } +unlock: mutex_unlock(&kone->kone_lock); + if (retval) + return retval; + return sizeof(struct kone_settings); } static BIN_ATTR(settings, 0660, kone_sysfs_read_settings, diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c new file mode 100644 index 000000000000..cd7ada48b1d9 --- /dev/null +++ b/drivers/hid/hid-vivaldi.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * HID support for Vivaldi Keyboard + * + * Copyright 2020 Google LLC. + * Author: Sean O'Brien + */ + +#include +#include + +#define MIN_FN_ROW_KEY 1 +#define MAX_FN_ROW_KEY 24 +#define HID_VD_FN_ROW_PHYSMAP 0x00000001 +#define HID_USAGE_FN_ROW_PHYSMAP (HID_UP_GOOGLEVENDOR | HID_VD_FN_ROW_PHYSMAP) + +static struct hid_driver hid_vivaldi; + +struct vivaldi_data { + u32 function_row_physmap[MAX_FN_ROW_KEY - MIN_FN_ROW_KEY + 1]; + int max_function_row_key; +}; + +static ssize_t function_row_physmap_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct vivaldi_data *drvdata = hid_get_drvdata(hdev); + ssize_t size = 0; + int i; + + if (!drvdata->max_function_row_key) + return 0; + + for (i = 0; i < drvdata->max_function_row_key; i++) + size += sprintf(buf + size, "%02X ", + drvdata->function_row_physmap[i]); + size += sprintf(buf + size, "\n"); + return size; +} + +DEVICE_ATTR_RO(function_row_physmap); +static struct attribute *sysfs_attrs[] = { + &dev_attr_function_row_physmap.attr, + NULL +}; + +static const struct attribute_group input_attribute_group = { + .attrs = sysfs_attrs +}; + +static int vivaldi_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + struct vivaldi_data *drvdata; + int ret; + + drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); + hid_set_drvdata(hdev, drvdata); + + ret = hid_parse(hdev); + if (ret) + return ret; + + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); +} + +static void vivaldi_feature_mapping(struct hid_device *hdev, + struct hid_field *field, + struct hid_usage *usage) +{ + struct vivaldi_data *drvdata = hid_get_drvdata(hdev); + int fn_key; + int ret; + u32 report_len; + u8 *buf; + + if (field->logical != HID_USAGE_FN_ROW_PHYSMAP || + (usage->hid & HID_USAGE_PAGE) != HID_UP_ORDINAL) + return; + + fn_key = (usage->hid & HID_USAGE); + if (fn_key < MIN_FN_ROW_KEY || fn_key > MAX_FN_ROW_KEY) + return; + if (fn_key > drvdata->max_function_row_key) + drvdata->max_function_row_key = fn_key; + + buf = hid_alloc_report_buf(field->report, GFP_KERNEL); + if (!buf) + return; + + report_len = hid_report_len(field->report); + ret = hid_hw_raw_request(hdev, field->report->id, buf, + report_len, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + if (ret < 0) { + dev_warn(&hdev->dev, "failed to fetch feature %d\n", + field->report->id); + goto out; + } + + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, + report_len, 0); + if (ret) { + dev_warn(&hdev->dev, "failed to report feature %d\n", + field->report->id); + goto out; + } + + drvdata->function_row_physmap[fn_key - MIN_FN_ROW_KEY] = + field->value[usage->usage_index]; + +out: + kfree(buf); +} + +static int vivaldi_input_configured(struct hid_device *hdev, + struct hid_input *hidinput) +{ + return sysfs_create_group(&hdev->dev.kobj, &input_attribute_group); +} + +static const struct hid_device_id vivaldi_table[] = { + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_VIVALDI, HID_ANY_ID, + HID_ANY_ID) }, + { } +}; + +MODULE_DEVICE_TABLE(hid, vivaldi_table); + +static struct hid_driver hid_vivaldi = { + .name = "hid-vivaldi", + .id_table = vivaldi_table, + .probe = vivaldi_probe, + .feature_mapping = vivaldi_feature_mapping, + .input_configured = vivaldi_input_configured, +}; + +module_hid_driver(hid_vivaldi); + +MODULE_AUTHOR("Sean O'Brien"); +MODULE_DESCRIPTION("HID vivaldi driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index e484c3618dec..41012681cafd 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1586,7 +1586,7 @@ struct wiiproto_handler { void (*func)(struct wiimote_data *wdata, const __u8 *payload); }; -static struct wiiproto_handler handlers[] = { +static const struct wiiproto_handler handlers[] = { { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, { .id = WIIPROTO_REQ_STATUS, .size = 2, .func = handler_status_K }, { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data }, @@ -1618,19 +1618,19 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { struct wiimote_data *wdata = hid_get_drvdata(hdev); - struct wiiproto_handler *h; + const struct wiiproto_handler *h; int i; unsigned long flags; if (size < 1) return -EINVAL; - spin_lock_irqsave(&wdata->state.lock, flags); - for (i = 0; handlers[i].id; ++i) { h = &handlers[i]; if (h->id == raw_data[0] && h->size < size) { + spin_lock_irqsave(&wdata->state.lock, flags); h->func(wdata, &raw_data[1]); + spin_unlock_irqrestore(&wdata->state.lock, flags); break; } } @@ -1639,8 +1639,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0], size); - spin_unlock_irqrestore(&wdata->state.lock, flags); - return 0; } diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index dbd04492825d..786e3e9af1c9 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -323,7 +323,7 @@ static int i2c_hid_get_report(struct i2c_client *client, u8 reportType, * @reportType: 0x03 for HID_FEATURE_REPORT ; 0x02 for HID_OUTPUT_REPORT * @reportID: the report ID * @buf: the actual data to transfer, without the report ID - * @len: size of buf + * @data_len: size of buf * @use_data: true: use SET_REPORT HID command, false: send plain OUTPUT report */ static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType, @@ -935,6 +935,14 @@ static void i2c_hid_acpi_fix_up_power(struct device *dev) acpi_device_fix_up_power(adev); } +static void i2c_hid_acpi_enable_wakeup(struct device *dev) +{ + if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { + device_set_wakeup_capable(dev, true); + device_set_wakeup_enable(dev, false); + } +} + static const struct acpi_device_id i2c_hid_acpi_match[] = { {"ACPI0C50", 0 }, {"PNP0C50", 0 }, @@ -949,6 +957,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client, } static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {} + +static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {} #endif #ifdef CONFIG_OF @@ -1076,6 +1086,8 @@ static int i2c_hid_probe(struct i2c_client *client, i2c_hid_acpi_fix_up_power(&client->dev); + i2c_hid_acpi_enable_wakeup(&client->dev); + device_enable_async_suspend(&client->dev); /* Make sure there is something at this address */ @@ -1268,6 +1280,7 @@ static struct i2c_driver i2c_hid_driver = { .driver = { .name = "i2c_hid", .pm = &i2c_hid_pm, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .acpi_match_table = ACPI_PTR(i2c_hid_acpi_match), .of_match_table = of_match_ptr(i2c_hid_of_match), }, diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c index c47c3328a0f4..bba29cd36d29 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.c +++ b/drivers/hid/intel-ish-hid/ishtp/bus.c @@ -502,8 +502,6 @@ static void ishtp_bus_remove_device(struct ishtp_cl_device *device) int ishtp_cl_driver_register(struct ishtp_cl_driver *driver, struct module *owner) { - int err; - if (!ishtp_device_ready) return -ENODEV; @@ -511,11 +509,7 @@ int ishtp_cl_driver_register(struct ishtp_cl_driver *driver, driver->driver.owner = owner; driver->driver.bus = &ishtp_cl_bus_type; - err = driver_register(&driver->driver); - if (err) - return err; - - return 0; + return driver_register(&driver->driver); } EXPORT_SYMBOL(ishtp_cl_driver_register); diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 83dfec327c42..1bd0eb71559c 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2773,7 +2773,9 @@ static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *repo if (report->type != HID_INPUT_REPORT) return -1; - if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) + if (WACOM_PAD_FIELD(field)) + return 0; + else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) wacom_wac_pen_report(hdev, report); else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) wacom_wac_finger_report(hdev, report); diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 410f1fab519c..0cde10fe0e71 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -180,7 +180,7 @@ void hv_synic_enable_regs(unsigned int cpu) /* Setup the shared SINT. */ hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); - shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR; + shared_sint.vector = hv_get_vector(); shared_sint.masked = false; shared_sint.auto_eoi = hv_recommend_using_aeoi(); hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 7b8816c2e5f9..4fad3e6745e5 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -48,6 +48,10 @@ static int hyperv_cpuhp_online; static void *hv_panic_page; +/* Values parsed from ACPI DSDT */ +static int vmbus_irq; +int vmbus_interrupt; + /* * Boolean to control whether to report panic messages over Hyper-V. * @@ -1347,7 +1351,7 @@ static void vmbus_isr(void) tasklet_schedule(&hv_cpu->msg_dpc); } - add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0); + add_interrupt_randomness(hv_get_vector(), 0); } /* @@ -1430,7 +1434,9 @@ static int vmbus_bus_init(void) if (ret) return ret; - hv_setup_vmbus_irq(vmbus_isr); + ret = hv_setup_vmbus_irq(vmbus_irq, vmbus_isr); + if (ret) + goto err_setup; ret = hv_synic_alloc(); if (ret) @@ -1505,7 +1511,7 @@ static int vmbus_bus_init(void) hv_synic_free(); err_alloc: hv_remove_vmbus_irq(); - +err_setup: bus_unregister(&hv_bus); unregister_sysctl_table(hv_ctl_table_hdr); hv_ctl_table_hdr = NULL; @@ -2070,6 +2076,7 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) struct resource *new_res; struct resource **old_res = &hyperv_mmio; struct resource **prev_res = NULL; + struct resource r; switch (res->type) { @@ -2088,6 +2095,23 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) end = res->data.address64.address.maximum; break; + /* + * The IRQ information is needed only on ARM64, which Hyper-V + * sets up in the extended format. IRQ information is present + * on x86/x64 in the non-extended format but it is not used by + * Linux. So don't bother checking for the non-extended format. + */ + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + if (!acpi_dev_resource_interrupt(res, 0, &r)) { + pr_err("Unable to parse Hyper-V ACPI interrupt\n"); + return AE_ERROR; + } + /* ARM64 INTID for VMbus */ + vmbus_interrupt = res->data.extended_irq.interrupts[0]; + /* Linux IRQ number */ + vmbus_irq = r.start; + return AE_OK; + default: /* Unused resource type */ return AE_OK; diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 8d0d76ad319d..f44947043e5a 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -144,8 +144,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) if (err) goto err_cleanup_nand; - oxnas->chips[oxnas->nchips] = chip; - ++oxnas->nchips; + oxnas->chips[oxnas->nchips++] = chip; } /* Exit if no chips found */ diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 39deb22a4180..ee33b8ec62bb 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -119,6 +119,7 @@ config STI_CONSOLE bool "STI text console" depends on PARISC && HAS_IOMEM select FONT_SUPPORT + select CRC32 default y help The STI console is the builtin display/keyboard on HP-PARISC diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index e7fd995d3aea..1b451165311c 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -2,7 +2,7 @@ * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2002 Helge Deller + * Copyright (C) 2002-2020 Helge Deller * * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, * which were @@ -43,6 +43,9 @@ #include #include #include +#include +#include +#include #include @@ -52,28 +55,16 @@ #define BLANK 0 static int vga_is_gfx; +#define STI_DEF_FONT sticon_sti->font + +/* borrowed from fbcon.c */ +#define FNTREFCOUNT(fd) (fd->refcount) +#define FNTCRC(fd) (fd->crc) +static struct sti_cooked_font *font_data[MAX_NR_CONSOLES]; + /* this is the sti_struct used for this console */ static struct sti_struct *sticon_sti; -/* Software scrollback */ -static unsigned long softback_buf, softback_curr; -static unsigned long softback_in; -static unsigned long /* softback_top, */ softback_end; -static int softback_lines; - -/* software cursor */ -static int cursor_drawn; -#define CURSOR_DRAW_DELAY (1) -#define DEFAULT_CURSOR_BLINK_RATE (20) - -static int vbl_cursor_cnt; - -static inline void cursor_undrawn(void) -{ - vbl_cursor_cnt = 0; - cursor_drawn = 0; -} - static const char *sticon_startup(void) { return "STI console"; @@ -81,61 +72,43 @@ static const char *sticon_startup(void) static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) { - int redraw_cursor = 0; - if (vga_is_gfx || console_blanked) return; if (conp->vc_mode != KD_TEXT) return; -#if 0 - if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { - cursor_undrawn(); - redraw_cursor = 1; - } -#endif - sti_putc(sticon_sti, c, ypos, xpos); - - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; + sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]); } static void sticon_putcs(struct vc_data *conp, const unsigned short *s, int count, int ypos, int xpos) { - int redraw_cursor = 0; - if (vga_is_gfx || console_blanked) return; if (conp->vc_mode != KD_TEXT) return; -#if 0 - if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && - (p->cursor_x < (xpos + count))) { - cursor_undrawn(); - redraw_cursor = 1; - } -#endif - while (count--) { - sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++); + sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++, + font_data[conp->vc_num]); } - - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; } static void sticon_cursor(struct vc_data *conp, int mode) { unsigned short car1; + /* no cursor update if screen is blanked */ + if (vga_is_gfx || console_blanked) + return; + car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; switch (mode) { case CM_ERASE: - sti_putc(sticon_sti, car1, conp->state.y, conp->state.x); + sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, + font_data[conp->vc_num]); break; case CM_MOVE: case CM_DRAW: @@ -146,7 +119,7 @@ static void sticon_cursor(struct vc_data *conp, int mode) case CUR_TWO_THIRDS: case CUR_BLOCK: sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), - conp->state.y, conp->state.x); + conp->state.y, conp->state.x, font_data[conp->vc_num]); break; } break; @@ -165,42 +138,164 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t, switch (dir) { case SM_UP: - sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols); - sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char); + sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols, + font_data[conp->vc_num]); + sti_clear(sti, b - count, 0, count, conp->vc_cols, + conp->vc_video_erase_char, font_data[conp->vc_num]); break; case SM_DOWN: - sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols); - sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char); + sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols, + font_data[conp->vc_num]); + sti_clear(sti, t, 0, count, conp->vc_cols, + conp->vc_video_erase_char, font_data[conp->vc_num]); break; } return false; } +static int sticon_set_def_font(int unit, struct console_font *op) +{ + if (font_data[unit] != STI_DEF_FONT) { + if (--FNTREFCOUNT(font_data[unit]) == 0) { + kfree(font_data[unit]->raw_ptr); + kfree(font_data[unit]); + } + font_data[unit] = STI_DEF_FONT; + } + + return 0; +} + +static int sticon_set_font(struct vc_data *vc, struct console_font *op) +{ + struct sti_struct *sti = sticon_sti; + int vc_cols, vc_rows, vc_old_cols, vc_old_rows; + int unit = vc->vc_num; + int w = op->width; + int h = op->height; + int size, i, bpc, pitch; + struct sti_rom_font *new_font; + struct sti_cooked_font *cooked_font; + unsigned char *data = op->data, *p; + + if ((w < 6) || (h < 6) || (w > 32) || (h > 32) + || (op->charcount != 256 && op->charcount != 512)) + return -EINVAL; + pitch = ALIGN(w, 8) / 8; + bpc = pitch * h; + size = bpc * op->charcount; + + new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM); + if (!new_font) + return -ENOMEM; + + new_font->first_char = 0; + new_font->last_char = op->charcount - 1; + new_font->width = w; + new_font->height = h; + new_font->font_type = STI_FONT_HPROMAN8; + new_font->bytes_per_char = bpc; + new_font->underline_height = 0; + new_font->underline_pos = 0; + + cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); + if (!cooked_font) { + kfree(new_font); + return -ENOMEM; + } + cooked_font->raw = new_font; + cooked_font->raw_ptr = new_font; + cooked_font->width = w; + cooked_font->height = h; + FNTREFCOUNT(cooked_font) = 0; /* usage counter */ + + p = (unsigned char *) new_font; + p += sizeof(*new_font); + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, bpc); + data += pitch*32; + p += bpc; + } + FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font)); + sti_font_convert_bytemode(sti, cooked_font); + new_font = cooked_font->raw_ptr; + + /* check if font is already used by other console */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (font_data[i] != STI_DEF_FONT + && (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) { + kfree(new_font); + kfree(cooked_font); + /* current font is the same as the new one */ + if (i == unit) + return 0; + cooked_font = font_data[i]; + new_font = cooked_font->raw_ptr; + break; + } + } + + /* clear screen with old font: we now may have less rows */ + vc_old_rows = vc->vc_rows; + vc_old_cols = vc->vc_cols; + sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols, + vc->vc_video_erase_char, font_data[vc->vc_num]); + + /* delete old font in case it is a user font */ + sticon_set_def_font(unit, NULL); + + FNTREFCOUNT(cooked_font)++; + font_data[unit] = cooked_font; + + vc_cols = sti_onscreen_x(sti) / cooked_font->width; + vc_rows = sti_onscreen_y(sti) / cooked_font->height; + vc_resize(vc, vc_cols, vc_rows); + + /* need to repaint screen if cols & rows are same as old font */ + if (vc_cols == vc_old_cols && vc_rows == vc_old_rows) + update_screen(vc); + + return 0; +} + +static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name) +{ + return sticon_set_def_font(vc->vc_num, op); +} + +static int sticon_font_set(struct vc_data *vc, struct console_font *font, + unsigned int flags) +{ + return sticon_set_font(vc, font); +} + static void sticon_init(struct vc_data *c, int init) { struct sti_struct *sti = sticon_sti; int vc_cols, vc_rows; sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0); - vc_cols = sti_onscreen_x(sti) / sti->font_width; - vc_rows = sti_onscreen_y(sti) / sti->font_height; + vc_cols = sti_onscreen_x(sti) / sti->font->width; + vc_rows = sti_onscreen_y(sti) / sti->font->height; c->vc_can_do_color = 1; if (init) { c->vc_cols = vc_cols; c->vc_rows = vc_rows; } else { - /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */ - /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */ vc_resize(c, vc_cols, vc_rows); -/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */ } } static void sticon_deinit(struct vc_data *c) { + int i; + + /* free memory used by user font */ + for (i = 0; i < MAX_NR_CONSOLES; i++) + sticon_set_def_font(i, NULL); } static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, @@ -209,7 +304,8 @@ static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, if (!height || !width) return; - sti_clear(sticon_sti, sy, sx, height, width, conp->vc_video_erase_char); + sti_clear(sticon_sti, sy, sx, height, width, + conp->vc_video_erase_char, font_data[conp->vc_num]); } static int sticon_switch(struct vc_data *conp) @@ -224,64 +320,13 @@ static int sticon_blank(struct vc_data *c, int blank, int mode_switch) vga_is_gfx = 0; return 1; } - sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK); + sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, + font_data[c->vc_num]); if (mode_switch) vga_is_gfx = 1; return 1; } -static u16 *sticon_screen_pos(const struct vc_data *conp, int offset) -{ - int line; - unsigned long p; - - if (conp->vc_num != fg_console || !softback_lines) - return (u16 *)(conp->vc_origin + offset); - line = offset / conp->vc_size_row; - if (line >= softback_lines) - return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row); - p = softback_curr + offset; - if (p >= softback_end) - p += softback_buf - softback_end; - return (u16 *)p; -} - -static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, - int *px, int *py) -{ - int x, y; - unsigned long ret; - if (pos >= conp->vc_origin && pos < conp->vc_scr_end) { - unsigned long offset = (pos - conp->vc_origin) / 2; - - x = offset % conp->vc_cols; - y = offset / conp->vc_cols; - if (conp->vc_num == fg_console) - y += softback_lines; - ret = pos + (conp->vc_cols - x) * 2; - } else if (conp->vc_num == fg_console && softback_lines) { - unsigned long offset = pos - softback_curr; - - if (pos < softback_curr) - offset += softback_end - softback_buf; - offset /= 2; - x = offset % conp->vc_cols; - y = offset / conp->vc_cols; - ret = pos + (conp->vc_cols - x) * 2; - if (ret == softback_end) - ret = softback_buf; - if (ret == softback_in) - ret = conp->vc_origin; - } else { - /* Should not happen */ - x = y = 0; - ret = conp->vc_origin; - } - if (px) *px = x; - if (py) *py = y; - return ret; -} - static u8 sticon_build_attr(struct vc_data *conp, u8 color, enum vc_intensity intens, bool blink, bool underline, bool reverse, @@ -312,10 +357,6 @@ static void sticon_invert_region(struct vc_data *conp, u16 *p, int count) } } -static void sticon_save_screen(struct vc_data *conp) -{ -} - static const struct consw sti_con = { .owner = THIS_MODULE, .con_startup = sticon_startup, @@ -328,18 +369,18 @@ static const struct consw sti_con = { .con_scroll = sticon_scroll, .con_switch = sticon_switch, .con_blank = sticon_blank, - .con_save_screen = sticon_save_screen, + .con_font_set = sticon_font_set, + .con_font_default = sticon_font_default, .con_build_attr = sticon_build_attr, .con_invert_region = sticon_invert_region, - .con_screen_pos = sticon_screen_pos, - .con_getxy = sticon_getxy, }; static int __init sticonsole_init(void) { - int err; + int err, i; + /* already initialized ? */ if (sticon_sti) return 0; @@ -348,14 +389,16 @@ static int __init sticonsole_init(void) if (!sticon_sti) return -ENODEV; - if (conswitchp == &dummy_con) { - printk(KERN_INFO "sticon: Initializing STI text console.\n"); - console_lock(); - err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); - console_unlock(); - return err; - } - return 0; + for (i = 0; i < MAX_NR_CONSOLES; i++) + font_data[i] = STI_DEF_FONT; + + pr_info("sticon: Initializing STI text console.\n"); + console_lock(); + err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, + PAGE0->mem_cons.cl_class != CL_DUPLEX); + console_unlock(); + + return err; } module_init(sticonsole_init); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 84c3ca37040a..6a26a364f9bd 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -4,7 +4,7 @@ * core code for console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2001-2013 Helge Deller + * Copyright (C) 2001-2020 Helge Deller * Copyright (C) 2001-2002 Thomas Bogendoerfer * * TODO: @@ -14,6 +14,8 @@ * */ +#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME + #include #include #include @@ -133,16 +135,17 @@ static const struct sti_font_flags default_font_flags = { }; void -sti_putc(struct sti_struct *sti, int c, int y, int x) +sti_putc(struct sti_struct *sti, int c, int y, int x, + struct sti_cooked_font *font) { struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; struct sti_font_inptr inptr_default = { - .font_start_addr= STI_PTR(sti->font->raw), + .font_start_addr = STI_PTR(font->raw), .index = c_index(sti, c), .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), - .dest_x = x * sti->font_width, - .dest_y = y * sti->font_height, + .dest_x = x * font->width, + .dest_y = y * font->height, }; struct sti_font_outptr *outptr = &sti->sti_data->font_outptr; s32 ret; @@ -193,18 +196,18 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, void sti_clear(struct sti_struct *sti, int src_y, int src_x, - int height, int width, int c) + int height, int width, int c, struct sti_cooked_font *font) { struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; struct sti_blkmv_inptr inptr_default = { .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), - .src_x = src_x * sti->font_width, - .src_y = src_y * sti->font_height, - .dest_x = src_x * sti->font_width, - .dest_y = src_y * sti->font_height, - .width = width * sti->font_width, - .height = height* sti->font_height, + .src_x = src_x * font->width, + .src_y = src_y * font->height, + .dest_x = src_x * font->width, + .dest_y = src_y * font->height, + .width = width * font->width, + .height = height * font->height, }; struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; @@ -225,16 +228,17 @@ static const struct sti_blkmv_flags default_blkmv_flags = { void sti_bmove(struct sti_struct *sti, int src_y, int src_x, - int dst_y, int dst_x, int height, int width) + int dst_y, int dst_x, int height, int width, + struct sti_cooked_font *font) { struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; struct sti_blkmv_inptr inptr_default = { - .src_x = src_x * sti->font_width, - .src_y = src_y * sti->font_height, - .dest_x = dst_x * sti->font_width, - .dest_y = dst_y * sti->font_height, - .width = width * sti->font_width, - .height = height* sti->font_height, + .src_x = src_x * font->width, + .src_y = src_y * font->height, + .dest_x = dst_x * font->width, + .dest_y = dst_y * font->height, + .width = width * font->width, + .height = height * font->height, }; struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; @@ -301,36 +305,32 @@ __setup("sti=", sti_setup); -static char *font_name[MAX_STI_ROMS]; -static int font_index[MAX_STI_ROMS], - font_height[MAX_STI_ROMS], - font_width[MAX_STI_ROMS]; +static char *font_name; +static int font_index, + font_height, + font_width; #ifndef MODULE static int sti_font_setup(char *str) { - char *x; - int i = 0; + /* + * The default font can be selected in various ways. + * a) sti_font=VGA8x16, sti_font=10x20, sti_font=10*20 selects + * an built-in Linux framebuffer font. + * b) sti_font=, where index is (1..x) with 1 selecting + * the first HP STI ROM built-in font.. + */ - /* we accept sti_font=VGA8x16, sti_font=10x20, sti_font=10*20 - * or sti_font=7 style command lines. */ + if (*str >= '0' && *str <= '9') { + char *x; - while (i='0' && *str<='9') { - if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) { - font_height[i] = simple_strtoul(str, NULL, 0); - font_width[i] = simple_strtoul(x+1, NULL, 0); - } else { - font_index[i] = simple_strtoul(str, NULL, 0); - } + if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) { + font_height = simple_strtoul(str, NULL, 0); + font_width = simple_strtoul(x+1, NULL, 0); } else { - font_name[i] = str; /* fb font name */ + font_index = simple_strtoul(str, NULL, 0); } - - if ((x = strchr(str, ','))) - *x++ = 0; - str = x; - - i++; + } else { + font_name = str; /* fb font name */ } return 1; @@ -344,7 +344,7 @@ static int sti_font_setup(char *str) * framebuffer font names (e.g. VGA8x16, SUN22x18). * This is only available if the fonts have been statically compiled * in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options. - * - sti_font= + * - sti_font= ( = 1,2,3,...) * most STI ROMs have built-in HP specific fonts, which can be selected * by giving the desired number to the sticon driver. * NOTE: This number is machine and STI ROM dependend. @@ -364,8 +364,7 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, { struct sti_glob_cfg_ext *cfg; - DPRINTK((KERN_INFO - "%d text planes\n" + pr_debug("%d text planes\n" "%4d x %4d screen resolution\n" "%4d x %4d offscreen\n" "%4d x %4d layout\n" @@ -382,12 +381,11 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5], glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7], glob_cfg->reent_lvl, - glob_cfg->save_addr)); + glob_cfg->save_addr); /* dump extended cfg */ cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr); - DPRINTK(( KERN_INFO - "monitor %d\n" + pr_debug("monitor %d\n" "in friendly mode: %d\n" "power consumption %d watts\n" "freq ref %d\n" @@ -396,20 +394,19 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, cfg->friendly_boot, cfg->power, cfg->freq_ref, - cfg->sti_mem_addr, sti_mem_request)); + cfg->sti_mem_addr, sti_mem_request); } static void sti_dump_outptr(struct sti_struct *sti) { - DPRINTK((KERN_INFO - "%d bits per pixel\n" + pr_debug("%d bits per pixel\n" "%d used bits\n" "%d planes\n" "attributes %08x\n", sti->sti_data->inq_outptr.bits_per_pixel, sti->sti_data->inq_outptr.bits_used, sti->sti_data->inq_outptr.planes, - sti->sti_data->inq_outptr.attributes)); + sti->sti_data->inq_outptr.attributes); } static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, @@ -448,8 +445,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, if (offs != PCI_ROM_ADDRESS && (offs < PCI_BASE_ADDRESS_0 || offs > PCI_BASE_ADDRESS_5)) { - printk (KERN_WARNING - "STI pci region mapping for region %d (%02x) can't be mapped\n", + pr_warn("STI pci region mapping for region %d (%02x) can't be mapped\n", i,sti->rm_entry[i]); continue; } @@ -464,14 +460,14 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, if (len) glob_cfg->region_ptrs[i] = sti->regions_phys[i]; - DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " + pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " "btlb=%d, sysonly=%d, cache=%d, last=%d\n", i, sti->regions_phys[i], glob_cfg->region_ptrs[i], len/1024, sti->regions[i].region_desc.btlb, sti->regions[i].region_desc.sys_only, sti->regions[i].region_desc.cache, - sti->regions[i].region_desc.last)); + sti->regions[i].region_desc.last); /* last entry reached ? */ if (sti->regions[i].region_desc.last) @@ -479,8 +475,8 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, } if (++i<8 && sti->regions[i].region) - printk(KERN_WARNING "%s: *future ptr (0x%8x) not yet supported !\n", - __FILE__, sti->regions[i].region); + pr_warn("future ptr (0x%8x) not yet supported !\n", + sti->regions[i].region); glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr); @@ -538,6 +534,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) } cooked_font->raw = nf; + cooked_font->raw_ptr = nf; cooked_font->next_font = NULL; cooked_rom->font_start = cooked_font; @@ -552,24 +549,38 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) } #endif -static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom, - int (*search_font_fnc)(struct sti_cooked_rom *, int, int)) +static int sti_search_font(struct sti_cooked_rom *rom, int height, int width) +{ + struct sti_cooked_font *font; + int i = 0; + + for (font = rom->font_start; font; font = font->next_font, i++) { + if ((font->raw->width == width) && + (font->raw->height == height)) + return i; + } + return 0; +} + +static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom) { struct sti_cooked_font *font; int i; - int index = num_sti_roms; /* check for framebuffer-font first */ - if ((font = sti_select_fbfont(rom, font_name[index]))) - return font; + if (!font_index) { + font = sti_select_fbfont(rom, font_name); + if (font) + return font; + } - if (font_width[index] && font_height[index]) - font_index[index] = search_font_fnc(rom, - font_height[index], font_width[index]); + if (font_width && font_height) + font_index = sti_search_font(rom, + font_height, font_width); - for (font = rom->font_start, i = font_index[index]; - font && (i > 0); - font = font->next_font, i--); + for (font = rom->font_start, i = font_index - 1; + font && (i > 0); + font = font->next_font, i--); if (font) return font; @@ -578,20 +589,35 @@ static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom, } -static void sti_dump_rom(struct sti_rom *rom) +static void sti_dump_rom(struct sti_struct *sti) { - printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", + struct sti_rom *rom = sti->rom->raw; + struct sti_cooked_font *font_start; + int nr; + + pr_info(" id %04x-%04x, conforms to spec rev. %d.%02x\n", rom->graphics_id[0], rom->graphics_id[1], rom->revno[0] >> 4, rom->revno[0] & 0x0f); - DPRINTK((" supports %d monitors\n", rom->num_mons)); - DPRINTK((" font start %08x\n", rom->font_start)); - DPRINTK((" region list %08x\n", rom->region_list)); - DPRINTK((" init_graph %08x\n", rom->init_graph)); - DPRINTK((" bus support %02x\n", rom->bus_support)); - DPRINTK((" ext bus support %02x\n", rom->ext_bus_support)); - DPRINTK((" alternate code type %d\n", rom->alt_code_type)); + pr_debug(" supports %d monitors\n", rom->num_mons); + pr_debug(" font start %08x\n", rom->font_start); + pr_debug(" region list %08x\n", rom->region_list); + pr_debug(" init_graph %08x\n", rom->init_graph); + pr_debug(" bus support %02x\n", rom->bus_support); + pr_debug(" ext bus support %02x\n", rom->ext_bus_support); + pr_debug(" alternate code type %d\n", rom->alt_code_type); + + font_start = sti->rom->font_start; + nr = 0; + while (font_start) { + struct sti_rom_font *f = font_start->raw; + + pr_info(" built-in font #%d: size %dx%d, chars %d-%d, bpc %d\n", ++nr, + f->width, f->height, + f->first_char, f->last_char, f->bytes_per_char); + font_start = font_start->next_font; + } } @@ -628,39 +654,34 @@ static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom, return 1; } - -static int sti_search_font(struct sti_cooked_rom *rom, int height, int width) -{ - struct sti_cooked_font *font; - int i = 0; - - for (font = rom->font_start; font; font = font->next_font, i++) { - if ((font->raw->width == width) && - (font->raw->height == height)) - return i; - } - return 0; -} - #define BMODE_RELOCATE(offset) offset = (offset) / 4; #define BMODE_LAST_ADDR_OFFS 0x50 -static void *sti_bmode_font_raw(struct sti_cooked_font *f) +void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f) { unsigned char *n, *p, *q; - int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); - + int size = f->raw->bytes_per_char * 256 + sizeof(struct sti_rom_font); + struct sti_rom_font *old_font; + + if (sti->wordmode) + return; + + old_font = f->raw_ptr; n = kcalloc(4, size, STI_LOWMEM); + f->raw_ptr = n; if (!n) - return NULL; + return; p = n + 3; - q = (unsigned char *)f->raw; + q = (unsigned char *) f->raw; while (size--) { *p = *q++; - p+=4; + p += 4; } - return n + 3; + /* store new ptr to byte-mode font and delete old font */ + f->raw = (struct sti_rom_font *) (n + 3); + kfree(old_font); } +EXPORT_SYMBOL(sti_font_convert_bytemode); static void sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest) @@ -747,7 +768,7 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, goto out_err; if (!sti_cook_fonts(cooked, raw)) { - printk(KERN_ERR "No font found for STI at %08lx\n", address); + pr_warn("No font found for STI at %08lx\n", address); goto out_err; } @@ -756,7 +777,8 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, address = (unsigned long) STI_PTR(raw); - pr_info("STI ROM supports 32 %sbit firmware functions.\n", + pr_info("STI %s ROM supports 32 %sbit firmware functions.\n", + wordmode ? "word mode" : "byte mode", raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 ? "and 64 " : ""); @@ -767,18 +789,17 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, sti->rom = cooked; sti->rom->raw = raw; - - sti->font = sti_select_font(sti->rom, sti_search_font); - sti->font_width = sti->font->raw->width; - sti->font_height = sti->font->raw->height; - if (!wordmode) - sti->font->raw = sti_bmode_font_raw(sti->font); + sti_dump_rom(sti); + + sti->wordmode = wordmode; + sti->font = sti_select_font(sti->rom); + sti->font->width = sti->font->raw->width; + sti->font->height = sti->font->raw->height; + sti_font_convert_bytemode(sti, sti->font); sti->sti_mem_request = raw->sti_mem_req; sti->graphics_id[0] = raw->graphics_id[0]; sti->graphics_id[1] = raw->graphics_id[1]; - - sti_dump_rom(raw); /* check if the ROM routines in this card are compatible */ if (wordmode || sti->graphics_id[1] != 0x09A02587) @@ -804,9 +825,9 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, return 1; msg_not_supported: - printk(KERN_ERR "Sorry, this GSC/STI card is not yet supported.\n"); - printk(KERN_ERR "Please see http://parisc-linux.org/faq/" - "graphics-howto.html for more info.\n"); + pr_warn("Sorry, this GSC/STI card is not yet supported.\n"); + pr_warn("Please see https://parisc.wiki.kernel.org/" + "index.php/Graphics_howto for more info.\n"); /* fall through */ out_err: kfree(raw); @@ -823,7 +844,7 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address, u32 sig; if (num_sti_roms >= MAX_STI_ROMS) { - printk(KERN_WARNING "maximum number of STI ROMS reached !\n"); + pr_warn("maximum number of STI ROMS reached !\n"); return NULL; } @@ -849,16 +870,15 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address, if (i != 1) { /* The ROM could have multiple architecture * dependent images (e.g. i386, parisc,...) */ - printk(KERN_WARNING - "PCI ROM is not a STI ROM type image (0x%8x)\n", i); + pr_warn("PCI ROM is not a STI ROM type image (0x%8x)\n", i); goto out_err; } sti->pd = pd; i = gsc_readl(address+0x0c); - DPRINTK(("PCI ROM size (from header) = %d kB\n", - le16_to_cpu(i>>16)*512/1024)); + pr_debug("PCI ROM size (from header) = %d kB\n", + le16_to_cpu(i>>16)*512/1024); rm_offset = le16_to_cpu(i & 0xffff); if (rm_offset) { /* read 16 bytes from the pci region mapper array */ @@ -867,29 +887,24 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address, *rm++ = gsc_readl(address+rm_offset+0x04); *rm++ = gsc_readl(address+rm_offset+0x08); *rm++ = gsc_readl(address+rm_offset+0x0c); - DPRINTK(("PCI region Mapper offset = %08x: ", - rm_offset)); - for (i=0; i<16; i++) - DPRINTK(("%02x ", sti->rm_entry[i])); - DPRINTK(("\n")); } address += le32_to_cpu(gsc_readl(address+8)); - DPRINTK(("sig %04x, PCI STI ROM at %08lx\n", sig, address)); + pr_debug("sig %04x, PCI STI ROM at %08lx\n", sig, address); goto test_rom; } ok = 0; if ((sig & 0xff) == 0x01) { - DPRINTK((" byte mode ROM at %08lx, hpa at %08lx\n", - address, hpa)); + pr_debug(" byte mode ROM at %08lx, hpa at %08lx\n", + address, hpa); ok = sti_read_rom(0, sti, address); } if ((sig & 0xffff) == 0x0303) { - DPRINTK((" word mode ROM at %08lx, hpa at %08lx\n", - address, hpa)); + pr_debug(" word mode ROM at %08lx, hpa at %08lx\n", + address, hpa); ok = sti_read_rom(1, sti, address); } @@ -906,7 +921,7 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address, unsigned long rom_base; rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE); pci_write_config_dword(sti->pd, PCI_ROM_ADDRESS, rom_base & ~PCI_ROM_ADDRESS_ENABLE); - DPRINTK((KERN_DEBUG "STI PCI ROM disabled\n")); + pr_debug("STI PCI ROM disabled\n"); } if (sti_init_graph(sti)) @@ -981,14 +996,14 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) rom_len = pci_resource_len(pd, PCI_ROM_RESOURCE); if (rom_base) { pci_write_config_dword(pd, PCI_ROM_ADDRESS, rom_base | PCI_ROM_ADDRESS_ENABLE); - DPRINTK((KERN_DEBUG "STI PCI ROM enabled at 0x%08lx\n", rom_base)); + pr_debug("STI PCI ROM enabled at 0x%08lx\n", rom_base); } - printk(KERN_INFO "STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)\n", + pr_info("STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)\n", rom_base, rom_len/1024, fb_base, fb_len/1024/1024); - DPRINTK((KERN_DEBUG "Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n", - rom_base, fb_base)); + pr_debug("Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n", + rom_base, fb_base); sti = sti_try_rom_generic(rom_base, fb_base, pd); if (sti) { @@ -998,8 +1013,7 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) } if (!sti) { - printk(KERN_WARNING "Unable to handle STI device '%s'\n", - pci_name(pd)); + pr_warn("Unable to handle STI device '%s'\n", pci_name(pd)); return -ENODEV; } #endif /* CONFIG_PCI */ @@ -1058,7 +1072,7 @@ static void sti_init_roms(void) sticore_initialized = 1; - printk(KERN_INFO "STI GSC/PCI core graphics driver " + pr_info("STI GSC/PCI core graphics driver " STI_DRIVERVERSION "\n"); /* Register drivers for native & PCI cards */ diff --git a/drivers/video/fbdev/sticore.h b/drivers/video/fbdev/sticore.h index fb8f58f9867a..c338f7848ae2 100644 --- a/drivers/video/fbdev/sticore.h +++ b/drivers/video/fbdev/sticore.h @@ -4,12 +4,6 @@ /* generic STI structures & functions */ -#if 0 -#define DPRINTK(x) printk x -#else -#define DPRINTK(x) -#endif - #define MAX_STI_ROMS 4 /* max no. of ROMs which this driver handles */ #define STI_REGION_MAX 8 /* hardcoded STI constants */ @@ -246,8 +240,12 @@ struct sti_rom_font { /* sticore internal font handling */ struct sti_cooked_font { - struct sti_rom_font *raw; + struct sti_rom_font *raw; /* native ptr for STI functions */ + void *raw_ptr; /* kmalloc'ed font data */ struct sti_cooked_font *next_font; + int height, width; + int refcount; + u32 crc; }; struct sti_cooked_rom { @@ -341,9 +339,6 @@ struct sti_all_data { struct sti_struct { spinlock_t lock; - /* the following fields needs to be filled in by the word/byte routines */ - int font_width; - int font_height; /* char **mon_strings; */ int sti_mem_request; u32 graphics_id[2]; @@ -362,6 +357,7 @@ struct sti_struct { struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */ + int wordmode; struct sti_cooked_font *font; /* ptr to selected font (cooked) */ struct pci_dev *pd; @@ -380,6 +376,7 @@ struct sti_struct { /* sticore interface functions */ struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ +void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f); /* sticore main function to call STI firmware */ @@ -391,12 +388,14 @@ int sti_call(const struct sti_struct *sti, unsigned long func, /* functions to call the STI ROM directly */ -void sti_putc(struct sti_struct *sti, int c, int y, int x); +void sti_putc(struct sti_struct *sti, int c, int y, int x, + struct sti_cooked_font *font); void sti_set(struct sti_struct *sti, int src_y, int src_x, - int height, int width, u8 color); + int height, int width, u8 color); void sti_clear(struct sti_struct *sti, int src_y, int src_x, - int height, int width, int c); + int height, int width, int c, struct sti_cooked_font *font); void sti_bmove(struct sti_struct *sti, int src_y, int src_x, - int dst_y, int dst_x, int height, int width); + int dst_y, int dst_x, int height, int width, + struct sti_cooked_font *font); #endif /* STICORE_H */ diff --git a/fs/direct-io.c b/fs/direct-io.c index 0353b322a00c..f6672c4030e3 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1159,22 +1159,13 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, * the early prefetch in the caller enough time. */ - if (align & blocksize_mask) { - if (bdev) - blkbits = blksize_bits(bdev_logical_block_size(bdev)); - blocksize_mask = (1 << blkbits) - 1; - if (align & blocksize_mask) - goto out; - } - /* watch out for a 0 len io from a tricksy fs */ if (iov_iter_rw(iter) == READ && !count) return 0; dio = kmem_cache_alloc(dio_cache, GFP_KERNEL); - retval = -ENOMEM; if (!dio) - goto out; + return -ENOMEM; /* * Believe it or not, zeroing out the page array caused a .5% * performance regression in a database benchmark. So, we take @@ -1183,32 +1174,32 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, memset(dio, 0, offsetof(struct dio, pages)); dio->flags = flags; - if (dio->flags & DIO_LOCKING) { - if (iov_iter_rw(iter) == READ) { - struct address_space *mapping = - iocb->ki_filp->f_mapping; - - /* will be released by direct_io_worker */ - inode_lock(inode); - - retval = filemap_write_and_wait_range(mapping, offset, - end - 1); - if (retval) { - inode_unlock(inode); - kmem_cache_free(dio_cache, dio); - goto out; - } - } + if (dio->flags & DIO_LOCKING && iov_iter_rw(iter) == READ) { + /* will be released by direct_io_worker */ + inode_lock(inode); } /* Once we sampled i_size check for reads beyond EOF */ dio->i_size = i_size_read(inode); if (iov_iter_rw(iter) == READ && offset >= dio->i_size) { - if (dio->flags & DIO_LOCKING) - inode_unlock(inode); - kmem_cache_free(dio_cache, dio); retval = 0; - goto out; + goto fail_dio; + } + + if (align & blocksize_mask) { + if (bdev) + blkbits = blksize_bits(bdev_logical_block_size(bdev)); + blocksize_mask = (1 << blkbits) - 1; + if (align & blocksize_mask) + goto fail_dio; + } + + if (dio->flags & DIO_LOCKING && iov_iter_rw(iter) == READ) { + struct address_space *mapping = iocb->ki_filp->f_mapping; + + retval = filemap_write_and_wait_range(mapping, offset, end - 1); + if (retval) + goto fail_dio; } /* @@ -1252,14 +1243,8 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, */ retval = sb_init_dio_done_wq(dio->inode->i_sb); } - if (retval) { - /* - * We grab i_mutex only for reads so we don't have - * to release it here - */ - kmem_cache_free(dio_cache, dio); - goto out; - } + if (retval) + goto fail_dio; } /* @@ -1362,7 +1347,13 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, } else BUG_ON(retval != -EIOCBQUEUED); -out: + return retval; + +fail_dio: + if (dio->flags & DIO_LOCKING && iov_iter_rw(iter) == READ) + inode_unlock(inode); + + kmem_cache_free(dio_cache, dio); return retval; } diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index fa9c951d3471..1f3f4326bf3c 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -189,7 +189,7 @@ static void group_adjust_blocks(struct super_block *sb, int group_no, /** * __rsv_window_dump() -- Dump the filesystem block allocation reservation map - * @rb_root: root of per-filesystem reservation rb tree + * @root: root of per-filesystem reservation rb tree * @verbose: verbose mode * @fn: function which wishes to dump the reservation map * @@ -282,7 +282,7 @@ goal_in_my_reservation(struct ext2_reserve_window *rsv, ext2_grpblk_t grp_goal, /** * search_reserve_window() - * @rb_root: root of reservation tree + * @root: root of reservation tree * @goal: target allocation block * * Find the reserved window which includes the goal, or the previous one @@ -859,7 +859,7 @@ static int find_next_reservable_window( * * failed: we failed to find a reservation window in this group * - * @rsv: the reservation + * @my_rsv: the reservation * * @grp_goal: The goal (group-relative). It is where the search for a * free reservable space should start from. diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 415c21f0e750..11c5c6fe75bb 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "ext2.h" #include "acl.h" #include "xattr.h" diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 6b37d58f1067..9af95c7a0bbe 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -532,6 +532,14 @@ static inline u64 quota_btobb(u64 bytes) return (bytes + (1 << XFS_BB_SHIFT) - 1) >> XFS_BB_SHIFT; } +static inline s64 copy_from_xfs_dqblk_ts(const struct fs_disk_quota *d, + __s32 timer, __s8 timer_hi) +{ + if (d->d_fieldmask & FS_DQ_BIGTIME) + return (u32)timer | (s64)timer_hi << 32; + return timer; +} + static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src) { dst->d_spc_hardlimit = quota_bbtob(src->d_blk_hardlimit); @@ -540,14 +548,17 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src) dst->d_ino_softlimit = src->d_ino_softlimit; dst->d_space = quota_bbtob(src->d_bcount); dst->d_ino_count = src->d_icount; - dst->d_ino_timer = src->d_itimer; - dst->d_spc_timer = src->d_btimer; + dst->d_ino_timer = copy_from_xfs_dqblk_ts(src, src->d_itimer, + src->d_itimer_hi); + dst->d_spc_timer = copy_from_xfs_dqblk_ts(src, src->d_btimer, + src->d_btimer_hi); dst->d_ino_warns = src->d_iwarns; dst->d_spc_warns = src->d_bwarns; dst->d_rt_spc_hardlimit = quota_bbtob(src->d_rtb_hardlimit); dst->d_rt_spc_softlimit = quota_bbtob(src->d_rtb_softlimit); dst->d_rt_space = quota_bbtob(src->d_rtbcount); - dst->d_rt_spc_timer = src->d_rtbtimer; + dst->d_rt_spc_timer = copy_from_xfs_dqblk_ts(src, src->d_rtbtimer, + src->d_rtbtimer_hi); dst->d_rt_spc_warns = src->d_rtbwarns; dst->d_fieldmask = 0; if (src->d_fieldmask & FS_DQ_ISOFT) @@ -639,10 +650,26 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id, return sb->s_qcop->set_dqblk(sb, qid, &qdq); } +static inline void copy_to_xfs_dqblk_ts(const struct fs_disk_quota *d, + __s32 *timer_lo, __s8 *timer_hi, s64 timer) +{ + *timer_lo = timer; + if (d->d_fieldmask & FS_DQ_BIGTIME) + *timer_hi = timer >> 32; +} + +static inline bool want_bigtime(s64 timer) +{ + return timer > S32_MAX || timer < S32_MIN; +} + static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src, int type, qid_t id) { memset(dst, 0, sizeof(*dst)); + if (want_bigtime(src->d_ino_timer) || want_bigtime(src->d_spc_timer) || + want_bigtime(src->d_rt_spc_timer)) + dst->d_fieldmask |= FS_DQ_BIGTIME; dst->d_version = FS_DQUOT_VERSION; dst->d_id = id; if (type == USRQUOTA) @@ -657,14 +684,17 @@ static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src, dst->d_ino_softlimit = src->d_ino_softlimit; dst->d_bcount = quota_btobb(src->d_space); dst->d_icount = src->d_ino_count; - dst->d_itimer = src->d_ino_timer; - dst->d_btimer = src->d_spc_timer; + copy_to_xfs_dqblk_ts(dst, &dst->d_itimer, &dst->d_itimer_hi, + src->d_ino_timer); + copy_to_xfs_dqblk_ts(dst, &dst->d_btimer, &dst->d_btimer_hi, + src->d_spc_timer); dst->d_iwarns = src->d_ino_warns; dst->d_bwarns = src->d_spc_warns; dst->d_rtb_hardlimit = quota_btobb(src->d_rt_spc_hardlimit); dst->d_rtb_softlimit = quota_btobb(src->d_rt_spc_softlimit); dst->d_rtbcount = quota_btobb(src->d_rt_space); - dst->d_rtbtimer = src->d_rt_spc_timer; + copy_to_xfs_dqblk_ts(dst, &dst->d_rtbtimer, &dst->d_rtbtimer_hi, + src->d_rt_spc_timer); dst->d_rtbwarns = src->d_rt_spc_warns; } diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index 58fc2a7c7fd1..e69a2bfdd81c 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -282,6 +282,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) d->dqb_curspace = cpu_to_le64(m->dqb_curspace); d->dqb_btime = cpu_to_le64(m->dqb_btime); d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); + d->dqb_pad = 0; if (qtree_entry_unused(info, dp)) d->dqb_itime = cpu_to_le64(1); } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 1509775da040..c76d563dec0e 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1551,11 +1551,7 @@ void reiserfs_read_locked_inode(struct inode *inode, * set version 1, version 2 could be used too, because stat data * key is the same in both versions */ - key.version = KEY_FORMAT_3_5; - key.on_disk_key.k_dir_id = dirino; - key.on_disk_key.k_objectid = inode->i_ino; - key.on_disk_key.k_offset = 0; - key.on_disk_key.k_type = 0; + _make_cpu_key(&key, KEY_FORMAT_3_5, dirino, inode->i_ino, 0, 0, 3); /* look for the object's stat data */ retval = search_item(inode->i_sb, &key, &path_to_sd); @@ -2163,7 +2159,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_inserted_sd: clear_nlink(inode); th->t_trans_id = 0; /* so the caller can't use this handle later */ - unlock_new_inode(inode); /* OK to do even if we hadn't locked it */ + if (inode->i_state & I_NEW) + unlock_new_inode(inode); iput(inode); return err; } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index a6bce5b1fb1d..1b9c7a387dc7 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1258,6 +1258,10 @@ static int reiserfs_parse_options(struct super_block *s, "turned on."); return 0; } + if (qf_names[qtype] != + REISERFS_SB(s)->s_qf_names[qtype]) + kfree(qf_names[qtype]); + qf_names[qtype] = NULL; if (*arg) { /* Some filename specified? */ if (REISERFS_SB(s)->s_qf_names[qtype] && strcmp(REISERFS_SB(s)->s_qf_names[qtype], @@ -1287,10 +1291,6 @@ static int reiserfs_parse_options(struct super_block *s, else *mount_options |= 1 << REISERFS_GRPQUOTA; } else { - if (qf_names[qtype] != - REISERFS_SB(s)->s_qf_names[qtype]) - kfree(qf_names[qtype]); - qf_names[qtype] = NULL; if (qtype == USRQUOTA) *mount_options &= ~(1 << REISERFS_USRQUOTA); else diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 28b241cd6987..fe63a7c3e0da 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -674,6 +674,13 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer, if (get_inode_sd_version(inode) == STAT_DATA_V1) return -EOPNOTSUPP; + /* + * priv_root needn't be initialized during mount so allow initial + * lookups to succeed. + */ + if (!REISERFS_SB(inode->i_sb)->priv_root) + return 0; + dentry = xattr_lookup(inode, name, XATTR_REPLACE); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); diff --git a/fs/udf/directory.c b/fs/udf/directory.c index d9523013096f..73720320f0ab 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -34,7 +34,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, fibh->soffset = fibh->eoffset; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - fi = udf_get_fileident(iinfo->i_ext.i_data - + fi = udf_get_fileident(iinfo->i_data - (iinfo->i_efe ? sizeof(struct extendedFileEntry) : sizeof(struct fileEntry)), diff --git a/fs/udf/file.c b/fs/udf/file.c index 628941a6b79a..ad8eefad27d7 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -50,7 +50,7 @@ static void __udf_adinicb_readpage(struct page *page) * So just sample it once and use the same value everywhere. */ kaddr = kmap_atomic(page); - memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, isize); + memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, isize); memset(kaddr + isize, 0, PAGE_SIZE - isize); flush_dcache_page(page); SetPageUptodate(page); @@ -76,8 +76,7 @@ static int udf_adinicb_writepage(struct page *page, BUG_ON(!PageLocked(page)); kaddr = kmap_atomic(page); - memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, - i_size_read(inode)); + memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, i_size_read(inode)); SetPageUptodate(page); kunmap_atomic(kaddr); mark_inode_dirty(inode); @@ -215,7 +214,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); case UDF_GETEABLOCK: return copy_to_user((char __user *)arg, - UDF_I(inode)->i_ext.i_data, + UDF_I(inode)->i_data, UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; default: return -ENOIOCTLCMD; diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 0adb40718a5d..84ed23edebfd 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -67,16 +67,16 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) iinfo->i_efe = 1; if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry), - GFP_KERNEL); + iinfo->i_data = kzalloc(inode->i_sb->s_blocksize - + sizeof(struct extendedFileEntry), + GFP_KERNEL); } else { iinfo->i_efe = 0; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct fileEntry), - GFP_KERNEL); + iinfo->i_data = kzalloc(inode->i_sb->s_blocksize - + sizeof(struct fileEntry), + GFP_KERNEL); } - if (!iinfo->i_ext.i_data) { + if (!iinfo->i_data) { iput(inode); return ERR_PTR(-ENOMEM); } diff --git a/fs/udf/inode.c b/fs/udf/inode.c index adaba8e8b326..bb89c3e43212 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -139,23 +139,26 @@ void udf_evict_inode(struct inode *inode) struct udf_inode_info *iinfo = UDF_I(inode); int want_delete = 0; - if (!inode->i_nlink && !is_bad_inode(inode)) { - want_delete = 1; - udf_setsize(inode, 0); - udf_update_inode(inode, IS_SYNC(inode)); + if (!is_bad_inode(inode)) { + if (!inode->i_nlink) { + want_delete = 1; + udf_setsize(inode, 0); + udf_update_inode(inode, IS_SYNC(inode)); + } + if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && + inode->i_size != iinfo->i_lenExtents) { + udf_warn(inode->i_sb, + "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n", + inode->i_ino, inode->i_mode, + (unsigned long long)inode->i_size, + (unsigned long long)iinfo->i_lenExtents); + } } truncate_inode_pages_final(&inode->i_data); invalidate_inode_buffers(inode); clear_inode(inode); - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && - inode->i_size != iinfo->i_lenExtents) { - udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n", - inode->i_ino, inode->i_mode, - (unsigned long long)inode->i_size, - (unsigned long long)iinfo->i_lenExtents); - } - kfree(iinfo->i_ext.i_data); - iinfo->i_ext.i_data = NULL; + kfree(iinfo->i_data); + iinfo->i_data = NULL; udf_clear_extent_cache(inode); if (want_delete) { udf_free_inode(inode); @@ -285,14 +288,14 @@ int udf_expand_file_adinicb(struct inode *inode) kaddr = kmap_atomic(page); memset(kaddr + iinfo->i_lenAlloc, 0x00, PAGE_SIZE - iinfo->i_lenAlloc); - memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, + memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, iinfo->i_lenAlloc); flush_dcache_page(page); SetPageUptodate(page); kunmap_atomic(kaddr); } down_write(&iinfo->i_data_sem); - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, + memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00, iinfo->i_lenAlloc); iinfo->i_lenAlloc = 0; if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) @@ -308,8 +311,7 @@ int udf_expand_file_adinicb(struct inode *inode) lock_page(page); down_write(&iinfo->i_data_sem); kaddr = kmap_atomic(page); - memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, - inode->i_size); + memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, inode->i_size); kunmap_atomic(kaddr); unlock_page(page); iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; @@ -396,8 +398,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, } mark_buffer_dirty_inode(dbh, inode); - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0, - iinfo->i_lenAlloc); + memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc); iinfo->i_lenAlloc = 0; eloc.logicalBlockNum = *block; eloc.partitionReferenceNum = @@ -1260,7 +1261,7 @@ int udf_setsize(struct inode *inode, loff_t newsize) if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { down_write(&iinfo->i_data_sem); udf_clear_extent_cache(inode); - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, + memset(iinfo->i_data + iinfo->i_lenEAttr + newsize, 0x00, bsize - newsize - udf_file_entry_alloc_offset(inode)); iinfo->i_lenAlloc = newsize; @@ -1411,7 +1412,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) sizeof(struct extendedFileEntry)); if (ret) goto out; - memcpy(iinfo->i_ext.i_data, + memcpy(iinfo->i_data, bh->b_data + sizeof(struct extendedFileEntry), bs - sizeof(struct extendedFileEntry)); } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { @@ -1420,7 +1421,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry)); if (ret) goto out; - memcpy(iinfo->i_ext.i_data, + memcpy(iinfo->i_data, bh->b_data + sizeof(struct fileEntry), bs - sizeof(struct fileEntry)); } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { @@ -1433,7 +1434,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) sizeof(struct unallocSpaceEntry)); if (ret) goto out; - memcpy(iinfo->i_ext.i_data, + memcpy(iinfo->i_data, bh->b_data + sizeof(struct unallocSpaceEntry), bs - sizeof(struct unallocSpaceEntry)); return 0; @@ -1614,8 +1615,8 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) static int udf_alloc_i_data(struct inode *inode, size_t size) { struct udf_inode_info *iinfo = UDF_I(inode); - iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL); - if (!iinfo->i_ext.i_data) + iinfo->i_data = kmalloc(size, GFP_KERNEL); + if (!iinfo->i_data) return -ENOMEM; return 0; } @@ -1706,7 +1707,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), - iinfo->i_ext.i_data, inode->i_sb->s_blocksize - + iinfo->i_data, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE); crclen = sizeof(struct unallocSpaceEntry); @@ -1772,7 +1773,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) if (iinfo->i_efe == 0) { memcpy(bh->b_data + sizeof(struct fileEntry), - iinfo->i_ext.i_data, + iinfo->i_data, inode->i_sb->s_blocksize - sizeof(struct fileEntry)); fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); @@ -1791,7 +1792,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) crclen = sizeof(struct fileEntry); } else { memcpy(bh->b_data + sizeof(struct extendedFileEntry), - iinfo->i_ext.i_data, + iinfo->i_data, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); efe->objectSize = @@ -2087,7 +2088,7 @@ void udf_write_aext(struct inode *inode, struct extent_position *epos, struct udf_inode_info *iinfo = UDF_I(inode); if (!epos->bh) - ptr = iinfo->i_ext.i_data + epos->offset - + ptr = iinfo->i_data + epos->offset - udf_file_entry_alloc_offset(inode) + iinfo->i_lenEAttr; else @@ -2179,7 +2180,7 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, if (!epos->bh) { if (!epos->offset) epos->offset = udf_file_entry_alloc_offset(inode); - ptr = iinfo->i_ext.i_data + epos->offset - + ptr = iinfo->i_data + epos->offset - udf_file_entry_alloc_offset(inode) + iinfo->i_lenEAttr; alen = udf_file_entry_alloc_offset(inode) + diff --git a/fs/udf/misc.c b/fs/udf/misc.c index 401e64cde1be..eab94527340d 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c @@ -52,9 +52,9 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, uint16_t crclen; struct udf_inode_info *iinfo = UDF_I(inode); - ea = iinfo->i_ext.i_data; + ea = iinfo->i_data; if (iinfo->i_lenEAttr) { - ad = iinfo->i_ext.i_data + iinfo->i_lenEAttr; + ad = iinfo->i_data + iinfo->i_lenEAttr; } else { ad = ea; size += sizeof(struct extendedAttrHeaderDesc); @@ -153,7 +153,7 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, uint32_t offset; struct udf_inode_info *iinfo = UDF_I(inode); - ea = iinfo->i_ext.i_data; + ea = iinfo->i_data; if (iinfo->i_lenEAttr) { struct extendedAttrHeaderDesc *eahd; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 77b6d89b9bcd..e169d8fe35b5 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -460,8 +460,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { block = dinfo->i_location.logicalBlockNum; fi = (struct fileIdentDesc *) - (dinfo->i_ext.i_data + - fibh->soffset - + (dinfo->i_data + fibh->soffset - udf_ext0_offset(dir) + dinfo->i_lenEAttr); } else { @@ -940,7 +939,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, mark_buffer_dirty_inode(epos.bh, inode); ea = epos.bh->b_data + udf_ext0_offset(inode); } else - ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr; + ea = iinfo->i_data + iinfo->i_lenEAttr; eoffset = sb->s_blocksize - udf_ext0_offset(inode); pc = (struct pathComponent *)ea; @@ -1120,7 +1119,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, retval = -EIO; if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { dir_fi = udf_get_fileident( - old_iinfo->i_ext.i_data - + old_iinfo->i_data - (old_iinfo->i_efe ? sizeof(struct extendedFileEntry) : sizeof(struct fileEntry)), diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 090baff83990..4cbf40575965 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c @@ -65,7 +65,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, } if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data + + loc = le32_to_cpu(((__le32 *)(iinfo->i_data + vdata->s_start_offset))[block]); goto translate; } diff --git a/fs/udf/super.c b/fs/udf/super.c index 1c42f544096d..faf2017ada11 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -168,7 +168,7 @@ static void init_once(void *foo) { struct udf_inode_info *ei = (struct udf_inode_info *)foo; - ei->i_ext.i_data = NULL; + ei->i_data = NULL; inode_init_once(&ei->vfs_inode); } @@ -854,7 +854,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) uint8_t *outstr; struct buffer_head *bh; uint16_t ident; - int ret = -ENOMEM; + int ret; struct timestamp *ts; outstr = kmalloc(128, GFP_NOFS); @@ -1006,18 +1006,10 @@ int udf_compute_nr_groups(struct super_block *sb, u32 partition) static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) { struct udf_bitmap *bitmap; - int nr_groups; - int size; - - nr_groups = udf_compute_nr_groups(sb, index); - size = sizeof(struct udf_bitmap) + - (sizeof(struct buffer_head *) * nr_groups); - - if (size <= PAGE_SIZE) - bitmap = kzalloc(size, GFP_KERNEL); - else - bitmap = vzalloc(size); /* TODO: get rid of vzalloc */ + int nr_groups = udf_compute_nr_groups(sb, index); + bitmap = kvzalloc(struct_size(bitmap, s_block_bitmap, nr_groups), + GFP_KERNEL); if (!bitmap) return NULL; @@ -1210,7 +1202,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) vat20 = (struct virtualAllocationTable20 *)bh->b_data; } else { vat20 = (struct virtualAllocationTable20 *) - vati->i_ext.i_data; + vati->i_data; } map->s_type_specific.s_virtual.s_start_offset = @@ -1353,6 +1345,12 @@ static int udf_load_sparable_map(struct super_block *sb, (int)spm->numSparingTables); return -EIO; } + if (le32_to_cpu(spm->sizeSparingTable) > sb->s_blocksize) { + udf_err(sb, "error loading logical volume descriptor: " + "Too big sparing table size (%u)\n", + le32_to_cpu(spm->sizeSparingTable)); + return -EIO; + } for (i = 0; i < spm->numSparingTables; i++) { loc = le32_to_cpu(spm->locSparingTable[i]); @@ -1698,7 +1696,8 @@ static noinline int udf_process_sequence( "Pointers (max %u supported)\n", UDF_MAX_TD_NESTING); brelse(bh); - return -EIO; + ret = -EIO; + goto out; } vdp = (struct volDescPtr *)bh->b_data; @@ -1718,7 +1717,8 @@ static noinline int udf_process_sequence( curr = get_volume_descriptor_record(ident, bh, &data); if (IS_ERR(curr)) { brelse(bh); - return PTR_ERR(curr); + ret = PTR_ERR(curr); + goto out; } /* Descriptor we don't care about? */ if (!curr) @@ -1740,28 +1740,31 @@ static noinline int udf_process_sequence( */ if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) { udf_err(sb, "Primary Volume Descriptor not found!\n"); - return -EAGAIN; + ret = -EAGAIN; + goto out; } ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block); if (ret < 0) - return ret; + goto out; if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) { ret = udf_load_logicalvol(sb, data.vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset); if (ret < 0) - return ret; + goto out; } /* Now handle prevailing Partition Descriptors */ for (i = 0; i < data.num_part_descs; i++) { ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block); if (ret < 0) - return ret; + goto out; } - - return 0; + ret = 0; +out: + kfree(data.part_descs_loc); + return ret; } /* diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 25ff91c7e94a..c973db239604 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -122,7 +122,7 @@ static int udf_symlink_filler(struct file *file, struct page *page) down_read(&iinfo->i_data_sem); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr; + symlink = iinfo->i_data + iinfo->i_lenEAttr; } else { bh = sb_bread(inode->i_sb, pos); diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index 4245d1f63258..06ff7006b822 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h @@ -45,11 +45,7 @@ struct udf_inode_info { unsigned i_strat4096 : 1; unsigned i_streamdir : 1; unsigned reserved : 25; - union { - struct short_ad *i_sad; - struct long_ad *i_lad; - __u8 *i_data; - } i_ext; + __u8 *i_data; struct kernel_lb_addr i_locStreamdir; __u64 i_lenStreams; struct rw_semaphore i_data_sem; diff --git a/fs/vboxsf/dir.c b/fs/vboxsf/dir.c index dd147b490982..4d569f14a8d8 100644 --- a/fs/vboxsf/dir.c +++ b/fs/vboxsf/dir.c @@ -134,7 +134,7 @@ static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) d_type = vboxsf_get_d_type(info->info.attr.mode); /* - * On 32 bit systems pos is 64 signed, while ino is 32 bit + * On 32-bit systems pos is 64-bit signed, while ino is 32-bit * unsigned so fake_ino may overflow, check for this. */ if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index c5edc5e08b94..c57799684170 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -89,7 +89,7 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) } } -void hv_setup_vmbus_irq(void (*handler)(void)); +int hv_setup_vmbus_irq(int irq, void (*handler)(void)); void hv_remove_vmbus_irq(void); void hv_enable_vmbus_irq(void); void hv_disable_vmbus_irq(void); @@ -99,6 +99,8 @@ void hv_remove_kexec_handler(void); void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); void hv_remove_crash_handler(void); +extern int vmbus_interrupt; + #if IS_ENABLED(CONFIG_HYPERV) /* * Hypervisor's notion of virtual processor ID is different from diff --git a/include/linux/hid.h b/include/linux/hid.h index c7044a14200e..58684657960b 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -163,6 +163,7 @@ struct hid_item { #define HID_UP_LNVENDOR 0xffa00000 #define HID_UP_SENSOR 0x00200000 #define HID_UP_ASUSVENDOR 0xff310000 +#define HID_UP_GOOGLEVENDOR 0xffd10000 #define HID_USAGE 0x0000ffff @@ -371,6 +372,7 @@ struct hid_item { #define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102 #define HID_GROUP_STEAM 0x0103 #define HID_GROUP_LOGITECH_27MHZ_DEVICE 0x0104 +#define HID_GROUP_VIVALDI 0x0105 /* * HID protocol status diff --git a/include/linux/scif.h b/include/linux/scif.h index eeb250b73c4b..329e695b8fe5 100644 --- a/include/linux/scif.h +++ b/include/linux/scif.h @@ -657,7 +657,7 @@ int scif_unregister(scif_epd_t epd, off_t offset, size_t len); * the negative of one of the following errors is returned. * * Errors: - * EACCESS - Attempt to write to a read-only range + * EACCES - Attempt to write to a read-only range * EBADF, ENOTTY - epd is not a valid endpoint descriptor * ECONNRESET - Connection reset by peer * EINVAL - rma_flags is invalid @@ -733,7 +733,7 @@ int scif_readfrom(scif_epd_t epd, off_t loffset, size_t len, off_t * the negative of one of the following errors is returned. * * Errors: - * EACCESS - Attempt to write to a read-only range + * EACCES - Attempt to write to a read-only range * EBADF, ENOTTY - epd is not a valid endpoint descriptor * ECONNRESET - Connection reset by peer * EINVAL - rma_flags is invalid @@ -815,7 +815,7 @@ int scif_writeto(scif_epd_t epd, off_t loffset, size_t len, off_t * the negative of one of the following errors is returned. * * Errors: - * EACCESS - Attempt to write to a read-only range + * EACCES - Attempt to write to a read-only range * EBADF, ENOTTY - epd is not a valid endpoint descriptor * ECONNRESET - Connection reset by peer * EINVAL - rma_flags is invalid @@ -895,7 +895,7 @@ int scif_vreadfrom(scif_epd_t epd, void *addr, size_t len, off_t roffset, * the negative of one of the following errors is returned. * * Errors: - * EACCESS - Attempt to write to a read-only range + * EACCES - Attempt to write to a read-only range * EBADF, ENOTTY - epd is not a valid endpoint descriptor * ECONNRESET - Connection reset by peer * EINVAL - rma_flags is invalid diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h index 03d890b80ebc..c71d909addda 100644 --- a/include/uapi/linux/dqblk_xfs.h +++ b/include/uapi/linux/dqblk_xfs.h @@ -61,12 +61,16 @@ typedef struct fs_disk_quota { __u64 d_ino_softlimit;/* preferred inode limit */ __u64 d_bcount; /* # disk blocks owned by the user */ __u64 d_icount; /* # inodes owned by the user */ - __s32 d_itimer; /* zero if within inode limits */ - /* if not, we refuse service */ + __s32 d_itimer; /* Zero if within inode limits. If + * not, we refuse service at this time + * (in seconds since Unix epoch) */ __s32 d_btimer; /* similar to above; for disk blocks */ __u16 d_iwarns; /* # warnings issued wrt num inodes */ __u16 d_bwarns; /* # warnings issued wrt disk blocks */ - __s32 d_padding2; /* padding2 - for future use */ + __s8 d_itimer_hi; /* upper 8 bits of timer values */ + __s8 d_btimer_hi; + __s8 d_rtbtimer_hi; + __s8 d_padding2; /* padding2 - for future use */ __u64 d_rtb_hardlimit;/* absolute limit on realtime blks */ __u64 d_rtb_softlimit;/* preferred limit on RT disk blks */ __u64 d_rtbcount; /* # realtime blocks owned */ @@ -121,6 +125,12 @@ typedef struct fs_disk_quota { #define FS_DQ_RTBCOUNT (1<<14) #define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT) +/* + * Quota expiration timestamps are 40-bit signed integers, with the upper 8 + * bits encoded in the _hi fields. + */ +#define FS_DQ_BIGTIME (1<<15) + /* * Various flags related to quotactl(2). */ diff --git a/init/main.c b/init/main.c index e880b4ecb314..1af84337cb18 100644 --- a/init/main.c +++ b/init/main.c @@ -468,7 +468,7 @@ static void __init setup_boot_config(const char *cmdline) static int __init warn_bootconfig(char *str) { - pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOTCONFIG is not set.\n"); + pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOT_CONFIG is not set.\n"); return 0; } early_param("bootconfig", warn_bootconfig); diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 5dbc40160990..a0e6f746de6c 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -22,7 +22,7 @@ * is later flushed into the main ring buffer via IRQ work. * * The alternative implementation is chosen transparently - * by examinig current printk() context mask stored in @printk_context + * by examining current printk() context mask stored in @printk_context * per-CPU variable. * * The implementation allows to flush the strings also from another CPU. diff --git a/lib/bitmap.c b/lib/bitmap.c index c13d859bc7ab..61394890788e 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -552,7 +552,7 @@ static inline bool end_of_region(char c) } /* - * The format allows commas and whitespases at the beginning + * The format allows commas and whitespaces at the beginning * of the region. */ static const char *bitmap_find_region(const char *str) diff --git a/samples/configfs/configfs_sample.c b/samples/configfs/configfs_sample.c index e2398d94e8da..f9008be7a8a1 100644 --- a/samples/configfs/configfs_sample.c +++ b/samples/configfs/configfs_sample.c @@ -7,19 +7,17 @@ * macros defined by configfs.h * * Based on sysfs: - * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel * * configfs Copyright (C) 2005 Oracle. All rights reserved. */ #include +#include #include #include - #include - - /* * 01-childless * @@ -40,8 +38,8 @@ struct childless { static inline struct childless *to_childless(struct config_item *item) { - return item ? container_of(to_configfs_subsystem(to_config_group(item)), - struct childless, subsys) : NULL; + return container_of(to_configfs_subsystem(to_config_group(item)), + struct childless, subsys); } static ssize_t childless_showme_show(struct config_item *item, char *page) @@ -64,17 +62,11 @@ static ssize_t childless_storeme_store(struct config_item *item, const char *page, size_t count) { struct childless *childless = to_childless(item); - unsigned long tmp; - char *p = (char *) page; + int ret; - tmp = simple_strtoul(p, &p, 10); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - if (tmp > INT_MAX) - return -ERANGE; - - childless->storeme = tmp; + ret = kstrtoint(page, 10, &childless->storeme); + if (ret) + return ret; return count; } @@ -117,7 +109,6 @@ static struct childless childless_subsys = { }, }; - /* ----------------------------------------------------------------- */ /* @@ -136,7 +127,7 @@ struct simple_child { static inline struct simple_child *to_simple_child(struct config_item *item) { - return item ? container_of(item, struct simple_child, item) : NULL; + return container_of(item, struct simple_child, item); } static ssize_t simple_child_storeme_show(struct config_item *item, char *page) @@ -148,17 +139,11 @@ static ssize_t simple_child_storeme_store(struct config_item *item, const char *page, size_t count) { struct simple_child *simple_child = to_simple_child(item); - unsigned long tmp; - char *p = (char *) page; + int ret; - tmp = simple_strtoul(p, &p, 10); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - if (tmp > INT_MAX) - return -ERANGE; - - simple_child->storeme = tmp; + ret = kstrtoint(page, 10, &simple_child->storeme); + if (ret) + return ret; return count; } @@ -176,7 +161,7 @@ static void simple_child_release(struct config_item *item) } static struct configfs_item_operations simple_child_item_ops = { - .release = simple_child_release, + .release = simple_child_release, }; static const struct config_item_type simple_child_type = { @@ -185,15 +170,14 @@ static const struct config_item_type simple_child_type = { .ct_owner = THIS_MODULE, }; - struct simple_children { struct config_group group; }; static inline struct simple_children *to_simple_children(struct config_item *item) { - return item ? container_of(to_config_group(item), - struct simple_children, group) : NULL; + return container_of(to_config_group(item), + struct simple_children, group); } static struct config_item *simple_children_make_item(struct config_group *group, @@ -208,8 +192,6 @@ static struct config_item *simple_children_make_item(struct config_group *group, config_item_init_type_name(&simple_child->item, name, &simple_child_type); - simple_child->storeme = 0; - return &simple_child->item; } @@ -263,7 +245,6 @@ static struct configfs_subsystem simple_children_subsys = { }, }; - /* ----------------------------------------------------------------- */ /* @@ -350,9 +331,8 @@ static struct configfs_subsystem *example_subsys[] = { static int __init configfs_example_init(void) { - int ret; - int i; struct configfs_subsystem *subsys; + int ret, i; for (i = 0; example_subsys[i]; i++) { subsys = example_subsys[i]; @@ -361,9 +341,8 @@ static int __init configfs_example_init(void) mutex_init(&subsys->su_mutex); ret = configfs_register_subsystem(subsys); if (ret) { - printk(KERN_ERR "Error %d while registering subsystem %s\n", - ret, - subsys->su_group.cg_item.ci_namebuf); + pr_err("Error %d while registering subsystem %s\n", + ret, subsys->su_group.cg_item.ci_namebuf); goto out_unregister; } } diff --git a/scripts/spelling.txt b/scripts/spelling.txt index cb46a79665f5..953f4a2de1e5 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -598,7 +598,6 @@ extenstion||extension extracter||extractor faied||failed faield||failed -falied||failed faild||failed failded||failed failer||failure @@ -795,7 +794,6 @@ interrup||interrupt interrups||interrupts interruptted||interrupted interupted||interrupted -interupt||interrupt intial||initial intialisation||initialisation intialised||initialised @@ -971,7 +969,6 @@ occurd||occurred occured||occurred occurence||occurrence occure||occurred -occured||occurred occuring||occurring offser||offset offet||offset @@ -1440,7 +1437,6 @@ udpate||update uesd||used uknown||unknown usccess||success -usupported||unsupported uncommited||uncommitted uncompatible||incompatible unconditionaly||unconditionally diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h index f9fd1325f5bd..506c06a6536f 100644 --- a/tools/arch/parisc/include/uapi/asm/mman.h +++ b/tools/arch/parisc/include/uapi/asm/mman.h @@ -39,6 +39,5 @@ #define MADV_SOFT_OFFLINE 101 /* MAP_32BIT is undefined on parisc, fix it for perf */ #define MAP_32BIT 0 -/* MAP_UNINITIALIZED is undefined on parisc, fix it for perf */ #define MAP_UNINITIALIZED 0 #endif diff --git a/tools/testing/kunit/configs/broken_on_uml.config b/tools/testing/kunit/configs/broken_on_uml.config index 239b9f03da2c..a7f0603d33f6 100644 --- a/tools/testing/kunit/configs/broken_on_uml.config +++ b/tools/testing/kunit/configs/broken_on_uml.config @@ -39,3 +39,4 @@ # CONFIG_QCOM_CPR is not set # CONFIG_RESET_BRCMSTB_RESCAL is not set # CONFIG_RESET_INTEL_GW is not set +# CONFIG_ADI_AXI_ADC is not set diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py index 425ef40067e7..ebf5f5763dee 100755 --- a/tools/testing/kunit/kunit.py +++ b/tools/testing/kunit/kunit.py @@ -17,6 +17,7 @@ from collections import namedtuple from enum import Enum, auto import kunit_config +import kunit_json import kunit_kernel import kunit_parser @@ -30,9 +31,9 @@ KunitBuildRequest = namedtuple('KunitBuildRequest', KunitExecRequest = namedtuple('KunitExecRequest', ['timeout', 'build_dir', 'alltests']) KunitParseRequest = namedtuple('KunitParseRequest', - ['raw_output', 'input_data']) + ['raw_output', 'input_data', 'build_dir', 'json']) KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', - 'build_dir', 'alltests', + 'build_dir', 'alltests', 'json', 'make_options']) KernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0] @@ -113,12 +114,22 @@ def parse_tests(request: KunitParseRequest) -> KunitResult: test_result = kunit_parser.TestResult(kunit_parser.TestStatus.SUCCESS, [], 'Tests not Parsed.') + if request.raw_output: kunit_parser.raw_output(request.input_data) else: test_result = kunit_parser.parse_run_tests(request.input_data) parse_end = time.time() + if request.json: + json_obj = kunit_json.get_json_result( + test_result=test_result, + def_config='kunit_defconfig', + build_dir=request.build_dir, + json_path=request.json) + if request.json == 'stdout': + print(json_obj) + if test_result.status != kunit_parser.TestStatus.SUCCESS: return KunitResult(KunitStatus.TEST_FAILURE, test_result, parse_end - parse_start) @@ -151,7 +162,9 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree, return exec_result parse_request = KunitParseRequest(request.raw_output, - exec_result.result) + exec_result.result, + request.build_dir, + request.json) parse_result = parse_tests(parse_request) run_end = time.time() @@ -195,7 +208,12 @@ def add_exec_opts(parser): def add_parse_opts(parser): parser.add_argument('--raw_output', help='don\'t format output from kernel', action='store_true') - + parser.add_argument('--json', + nargs='?', + help='Stores test results in a JSON, and either ' + 'prints to stdout or saves to file if a ' + 'filename is specified', + type=str, const='stdout', default=None) def main(argv, linux=None): parser = argparse.ArgumentParser( @@ -237,10 +255,16 @@ def main(argv, linux=None): cli_args = parser.parse_args(argv) + if get_kernel_root_path(): + os.chdir(get_kernel_root_path()) + if cli_args.subcommand == 'run': if not os.path.exists(cli_args.build_dir): os.mkdir(cli_args.build_dir) + if not os.path.exists(kunit_kernel.kunitconfig_path): + create_default_kunitconfig() + if not linux: linux = kunit_kernel.LinuxSourceTree() @@ -249,14 +273,18 @@ def main(argv, linux=None): cli_args.jobs, cli_args.build_dir, cli_args.alltests, + cli_args.json, cli_args.make_options) result = run_tests(linux, request) if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'config': - if cli_args.build_dir: - if not os.path.exists(cli_args.build_dir): - os.mkdir(cli_args.build_dir) + if cli_args.build_dir and ( + not os.path.exists(cli_args.build_dir)): + os.mkdir(cli_args.build_dir) + + if not os.path.exists(kunit_kernel.kunitconfig_path): + create_default_kunitconfig() if not linux: linux = kunit_kernel.LinuxSourceTree() @@ -270,10 +298,6 @@ def main(argv, linux=None): if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'build': - if cli_args.build_dir: - if not os.path.exists(cli_args.build_dir): - os.mkdir(cli_args.build_dir) - if not linux: linux = kunit_kernel.LinuxSourceTree() @@ -288,10 +312,6 @@ def main(argv, linux=None): if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'exec': - if cli_args.build_dir: - if not os.path.exists(cli_args.build_dir): - os.mkdir(cli_args.build_dir) - if not linux: linux = kunit_kernel.LinuxSourceTree() @@ -300,7 +320,9 @@ def main(argv, linux=None): cli_args.alltests) exec_result = exec_tests(linux, exec_request) parse_request = KunitParseRequest(cli_args.raw_output, - exec_result.result) + exec_result.result, + cli_args.build_dir, + cli_args.json) result = parse_tests(parse_request) kunit_parser.print_with_timestamp(( 'Elapsed time: %.3fs\n') % ( @@ -314,7 +336,9 @@ def main(argv, linux=None): with open(cli_args.file, 'r') as f: kunit_output = f.read().splitlines() request = KunitParseRequest(cli_args.raw_output, - kunit_output) + kunit_output, + cli_args.build_dir, + cli_args.json) result = parse_tests(request) if result.status != KunitStatus.SUCCESS: sys.exit(1) diff --git a/tools/testing/kunit/kunit_json.py b/tools/testing/kunit/kunit_json.py new file mode 100644 index 000000000000..624b31b2dbd6 --- /dev/null +++ b/tools/testing/kunit/kunit_json.py @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Generates JSON from KUnit results according to +# KernelCI spec: https://github.com/kernelci/kernelci-doc/wiki/Test-API +# +# Copyright (C) 2020, Google LLC. +# Author: Heidi Fahim + +import json +import os + +import kunit_parser + +from kunit_parser import TestStatus + +def get_json_result(test_result, def_config, build_dir, json_path): + sub_groups = [] + + # Each test suite is mapped to a KernelCI sub_group + for test_suite in test_result.suites: + sub_group = { + "name": test_suite.name, + "arch": "UM", + "defconfig": def_config, + "build_environment": build_dir, + "test_cases": [], + "lab_name": None, + "kernel": None, + "job": None, + "git_branch": "kselftest", + } + test_cases = [] + # TODO: Add attachments attribute in test_case with detailed + # failure message, see https://api.kernelci.org/schema-test-case.html#get + for case in test_suite.cases: + test_case = {"name": case.name, "status": "FAIL"} + if case.status == TestStatus.SUCCESS: + test_case["status"] = "PASS" + elif case.status == TestStatus.TEST_CRASHED: + test_case["status"] = "ERROR" + test_cases.append(test_case) + sub_group["test_cases"] = test_cases + sub_groups.append(sub_group) + test_group = { + "name": "KUnit Test Group", + "arch": "UM", + "defconfig": def_config, + "build_environment": build_dir, + "sub_groups": sub_groups, + "lab_name": None, + "kernel": None, + "job": None, + "git_branch": "kselftest", + } + json_obj = json.dumps(test_group, indent=4) + if json_path != 'stdout': + with open(json_path, 'w') as result_path: + result_path.write(json_obj) + root = __file__.split('tools/testing/kunit/')[0] + kunit_parser.print_with_timestamp( + "Test results stored in %s" % + os.path.join(root, result_path.name)) + return json_obj diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py index e20e2056cb38..b557b1e93f98 100644 --- a/tools/testing/kunit/kunit_kernel.py +++ b/tools/testing/kunit/kunit_kernel.py @@ -36,9 +36,9 @@ class LinuxSourceTreeOperations(object): try: subprocess.check_output(['make', 'mrproper'], stderr=subprocess.STDOUT) except OSError as e: - raise ConfigError('Could not call make command: ' + e) + raise ConfigError('Could not call make command: ' + str(e)) except subprocess.CalledProcessError as e: - raise ConfigError(e.output) + raise ConfigError(e.output.decode()) def make_olddefconfig(self, build_dir, make_options): command = ['make', 'ARCH=um', 'olddefconfig'] @@ -49,22 +49,27 @@ class LinuxSourceTreeOperations(object): try: subprocess.check_output(command, stderr=subprocess.STDOUT) except OSError as e: - raise ConfigError('Could not call make command: ' + e) + raise ConfigError('Could not call make command: ' + str(e)) except subprocess.CalledProcessError as e: - raise ConfigError(e.output) + raise ConfigError(e.output.decode()) - def make_allyesconfig(self): + def make_allyesconfig(self, build_dir, make_options): kunit_parser.print_with_timestamp( 'Enabling all CONFIGs for UML...') + command = ['make', 'ARCH=um', 'allyesconfig'] + if make_options: + command.extend(make_options) + if build_dir: + command += ['O=' + build_dir] process = subprocess.Popen( - ['make', 'ARCH=um', 'allyesconfig'], + command, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) process.wait() kunit_parser.print_with_timestamp( 'Disabling broken configs to run KUnit tests...') with ExitStack() as es: - config = open(KCONFIG_PATH, 'a') + config = open(get_kconfig_path(build_dir), 'a') disable = open(BROKEN_ALLCONFIG_PATH, 'r').read() config.write(disable) kunit_parser.print_with_timestamp( @@ -79,9 +84,9 @@ class LinuxSourceTreeOperations(object): try: subprocess.check_output(command, stderr=subprocess.STDOUT) except OSError as e: - raise BuildError('Could not call execute make: ' + e) + raise BuildError('Could not call execute make: ' + str(e)) except subprocess.CalledProcessError as e: - raise BuildError(e.output) + raise BuildError(e.output.decode()) def linux_bin(self, params, timeout, build_dir, outfile): """Runs the Linux UML binary. Must be named 'linux'.""" @@ -161,9 +166,9 @@ class LinuxSourceTree(object): return self.build_config(build_dir, make_options) def build_um_kernel(self, alltests, jobs, build_dir, make_options): - if alltests: - self._ops.make_allyesconfig() try: + if alltests: + self._ops.make_allyesconfig(build_dir, make_options) self._ops.make_olddefconfig(build_dir, make_options) self._ops.make(jobs, build_dir, make_options) except (ConfigError, BuildError) as e: diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py index 287c74d821c3..99c3c5671ea4 100755 --- a/tools/testing/kunit/kunit_tool_test.py +++ b/tools/testing/kunit/kunit_tool_test.py @@ -11,11 +11,13 @@ from unittest import mock import tempfile, shutil # Handling test_tmpdir +import json import os import kunit_config import kunit_parser import kunit_kernel +import kunit_json import kunit test_tmpdir = '' @@ -230,6 +232,37 @@ class KUnitParserTest(unittest.TestCase): result = kunit_parser.parse_run_tests(file.readlines()) self.assertEqual('kunit-resource-test', result.suites[0].name) +class KUnitJsonTest(unittest.TestCase): + + def _json_for(self, log_file): + with(open(get_absolute_path(log_file))) as file: + test_result = kunit_parser.parse_run_tests(file) + json_obj = kunit_json.get_json_result( + test_result=test_result, + def_config='kunit_defconfig', + build_dir=None, + json_path='stdout') + return json.loads(json_obj) + + def test_failed_test_json(self): + result = self._json_for( + 'test_data/test_is_test_passed-failure.log') + self.assertEqual( + {'name': 'example_simple_test', 'status': 'FAIL'}, + result["sub_groups"][1]["test_cases"][0]) + + def test_crashed_test_json(self): + result = self._json_for( + 'test_data/test_is_test_passed-crash.log') + self.assertEqual( + {'name': 'example_simple_test', 'status': 'ERROR'}, + result["sub_groups"][1]["test_cases"][0]) + + def test_no_tests_json(self): + result = self._json_for( + 'test_data/test_is_test_passed-no_tests_run.log') + self.assertEqual(0, len(result['sub_groups'])) + class StrContains(str): def __eq__(self, other): return self in other diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 9018f45d631d..d9c283503159 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -88,10 +88,10 @@ endif # of the targets gets built. FORCE_TARGETS ?= -# Clear LDFLAGS and MAKEFLAGS if called from main -# Makefile to avoid test build failures when test -# Makefile doesn't have explicit build rules. -ifeq (1,$(MAKELEVEL)) +# Clear LDFLAGS and MAKEFLAGS when implicit rules are missing. This provides +# implicit rules to sub-test Makefiles which avoids build failures in test +# Makefile that don't have explicit build rules. +ifeq (,$(LINK.c)) override LDFLAGS = override MAKEFLAGS = endif @@ -206,6 +206,7 @@ KSFT_INSTALL_PATH := $(abspath $(KSFT_INSTALL_PATH)) # Avoid changing the rest of the logic here and lib.mk. INSTALL_PATH := $(KSFT_INSTALL_PATH) ALL_SCRIPT := $(INSTALL_PATH)/run_kselftest.sh +TEST_LIST := $(INSTALL_PATH)/kselftest-list.txt install: all ifdef INSTALL_PATH @@ -214,6 +215,8 @@ ifdef INSTALL_PATH install -m 744 kselftest/module.sh $(INSTALL_PATH)/kselftest/ install -m 744 kselftest/runner.sh $(INSTALL_PATH)/kselftest/ install -m 744 kselftest/prefix.pl $(INSTALL_PATH)/kselftest/ + install -m 744 run_kselftest.sh $(INSTALL_PATH)/ + rm -f $(TEST_LIST) @ret=1; \ for TARGET in $(TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ @@ -222,33 +225,18 @@ ifdef INSTALL_PATH ret=$$((ret * $$?)); \ done; exit $$ret; - @# Ask all targets to emit their test scripts - echo "#!/bin/sh" > $(ALL_SCRIPT) - echo "BASE_DIR=\$$(realpath \$$(dirname \$$0))" >> $(ALL_SCRIPT) - echo "cd \$$BASE_DIR" >> $(ALL_SCRIPT) - echo ". ./kselftest/runner.sh" >> $(ALL_SCRIPT) - echo "ROOT=\$$PWD" >> $(ALL_SCRIPT) - echo "if [ \"\$$1\" = \"--summary\" ]; then" >> $(ALL_SCRIPT) - echo " logfile=\$$BASE_DIR/output.log" >> $(ALL_SCRIPT) - echo " cat /dev/null > \$$logfile" >> $(ALL_SCRIPT) - echo "fi" >> $(ALL_SCRIPT) - @# While building run_kselftest.sh skip also non-existent TARGET dirs: + @# Ask all targets to emit their test scripts + @# While building kselftest-list.text skip also non-existent TARGET dirs: @# they could be the result of a build failure and should NOT be @# included in the generated runlist. for TARGET in $(TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ [ ! -d $(INSTALL_PATH)/$$TARGET ] && echo "Skipping non-existent dir: $$TARGET" && continue; \ - echo "[ -w /dev/kmsg ] && echo \"kselftest: Running tests in $$TARGET\" >> /dev/kmsg" >> $(ALL_SCRIPT); \ - echo "cd $$TARGET" >> $(ALL_SCRIPT); \ - echo -n "run_many" >> $(ALL_SCRIPT); \ echo -n "Emit Tests for $$TARGET\n"; \ - $(MAKE) -s --no-print-directory OUTPUT=$$BUILD_TARGET -C $$TARGET emit_tests >> $(ALL_SCRIPT); \ - echo "" >> $(ALL_SCRIPT); \ - echo "cd \$$ROOT" >> $(ALL_SCRIPT); \ + $(MAKE) -s --no-print-directory OUTPUT=$$BUILD_TARGET COLLECTION=$$TARGET \ + -C $$TARGET emit_tests >> $(TEST_LIST); \ done; - - chmod u+x $(ALL_SCRIPT) else $(error Error: set INSTALL_PATH to use install) endif diff --git a/tools/testing/selftests/firmware/.gitignore b/tools/testing/selftests/firmware/.gitignore new file mode 100644 index 000000000000..62abc92a94c4 --- /dev/null +++ b/tools/testing/selftests/firmware/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +fw_namespace diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index 7a17ea815736..30848ca36555 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -47,9 +47,9 @@ ARCH ?= $(SUBARCH) khdr: ifndef KSFT_KHDR_INSTALL_DONE ifeq (1,$(DEFAULT_INSTALL_HDR_PATH)) - make --no-builtin-rules ARCH=$(ARCH) -C $(top_srcdir) headers_install + $(MAKE) --no-builtin-rules ARCH=$(ARCH) -C $(top_srcdir) headers_install else - make --no-builtin-rules INSTALL_HDR_PATH=$$OUTPUT/usr \ + $(MAKE) --no-builtin-rules INSTALL_HDR_PATH=$$OUTPUT/usr \ ARCH=$(ARCH) -C $(top_srcdir) headers_install endif endif @@ -107,9 +107,8 @@ endif emit_tests: for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \ BASENAME_TEST=`basename $$TEST`; \ - echo " \\"; \ - echo -n " \"$$BASENAME_TEST\""; \ - done; \ + echo "$(COLLECTION):$$BASENAME_TEST"; \ + done # define if isn't already. It is undefined in make O= case. ifeq ($(RM),) diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh index 1aba83c87ad3..846c7ed71556 100644 --- a/tools/testing/selftests/livepatch/functions.sh +++ b/tools/testing/selftests/livepatch/functions.sh @@ -278,7 +278,7 @@ function check_result { # help differentiate repeated testing runs. Remove them with a # post-comparison sed filter. - result=$(dmesg | comm -13 "$SAVED_DMESG" - | \ + result=$(dmesg | comm --nocheck-order -13 "$SAVED_DMESG" - | \ grep -e 'livepatch:' -e 'test_klp' | \ grep -v '\(tainting\|taints\) kernel' | \ sed 's/^\[[ 0-9.]*\] //') diff --git a/tools/testing/selftests/netfilter/.gitignore b/tools/testing/selftests/netfilter/.gitignore new file mode 100644 index 000000000000..8448f74adfec --- /dev/null +++ b/tools/testing/selftests/netfilter/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +nf-queue diff --git a/tools/testing/selftests/ptrace/.gitignore b/tools/testing/selftests/ptrace/.gitignore index 7bebf9534a86..792318aaa30c 100644 --- a/tools/testing/selftests/ptrace/.gitignore +++ b/tools/testing/selftests/ptrace/.gitignore @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only get_syscall_info peeksiginfo +vmaccess diff --git a/tools/testing/selftests/run_kselftest.sh b/tools/testing/selftests/run_kselftest.sh new file mode 100755 index 000000000000..609a4ef9300e --- /dev/null +++ b/tools/testing/selftests/run_kselftest.sh @@ -0,0 +1,93 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Run installed kselftest tests. +# +BASE_DIR=$(realpath $(dirname $0)) +cd $BASE_DIR +TESTS="$BASE_DIR"/kselftest-list.txt +if [ ! -r "$TESTS" ] ; then + echo "$0: Could not find list of tests to run ($TESTS)" >&2 + available="" +else + available="$(cat "$TESTS")" +fi + +. ./kselftest/runner.sh +ROOT=$PWD + +usage() +{ + cat < $logfile + shift ;; + -t | --test) + TESTS="$TESTS $2" + shift 2 ;; + -c | --collection) + COLLECTIONS="$COLLECTIONS $2" + shift 2 ;; + -l | --list) + echo "$available" + exit 0 ;; + -n | --dry-run) + dryrun="echo" + shift ;; + -h | --help) + usage 0 ;; + "") + break ;; + *) + usage 1 ;; + esac +done + +# Add all selected collections to the explicit test list. +if [ -n "$COLLECTIONS" ]; then + for collection in $COLLECTIONS ; do + found="$(echo "$available" | grep "^$collection:")" + if [ -z "$found" ] ; then + echo "No such collection '$collection'" >&2 + exit 1 + fi + TESTS="$TESTS $found" + done +fi +# Replace available test list with explicitly selected tests. +if [ -n "$TESTS" ]; then + valid="" + for test in $TESTS ; do + found="$(echo "$available" | grep "^${test}$")" + if [ -z "$found" ] ; then + echo "No such test '$test'" >&2 + exit 1 + fi + valid="$valid $found" + done + available="$(echo "$valid" | sed -e 's/ /\n/g')" +fi + +collections=$(echo "$available" | cut -d: -f1 | uniq) +for collection in $collections ; do + [ -w /dev/kmsg ] && echo "kselftest: Running tests in $collection" >> /dev/kmsg + tests=$(echo "$available" | grep "^$collection:" | cut -d: -f2) + ($dryrun cd "$collection" && $dryrun run_many $tests) +done diff --git a/tools/testing/selftests/vm/config b/tools/testing/selftests/vm/config index 3ba674b64fa9..69dd0d1aa30b 100644 --- a/tools/testing/selftests/vm/config +++ b/tools/testing/selftests/vm/config @@ -3,3 +3,4 @@ CONFIG_USERFAULTFD=y CONFIG_TEST_VMALLOC=m CONFIG_DEVICE_PRIVATE=y CONFIG_TEST_HMM=m +CONFIG_GUP_BENCHMARK=y