This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.150-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 4.14.150-rc1
Dave Chinner dchinner@redhat.com xfs: clear sb->s_fs_info on mount failure
Janakarajan Natarajan Janakarajan.Natarajan@amd.com x86/asm: Fix MWAITX C-state hint value
Steven Rostedt (VMware) rostedt@goodmis.org tracing: Get trace_array reference for available_tracers files
Steven Rostedt (VMware) rostedt@goodmis.org ftrace: Get a reference counter for the trace_array on filter files
Srivatsa S. Bhat (VMware) srivatsa@csail.mit.edu tracing/hwlat: Don't ignore outer-loop duration when calculating max_latency
Srivatsa S. Bhat (VMware) srivatsa@csail.mit.edu tracing/hwlat: Report total time spent in all NMIs during the sample
Johan Hovold johan@kernel.org media: stkwebcam: fix runtime PM after driver unbind
Al Viro viro@zeniv.linux.org.uk Fix the locking in dcache_readdir() and friends
Paul Burton paul.burton@mips.com MIPS: Disable Loongson MMI instructions for kernel build
Trond Myklebust trondmy@gmail.com NFS: Fix O_DIRECT accounting of number of bytes read/written
Josef Bacik josef@toxicpanda.com btrfs: fix incorrect updating of log root tree
Andreas Klinger ak@it-klinger.de iio: adc: hx711: fix bug in sampling of data
Andreas Klinger ak@it-klinger.de iio: hx711: add delay until DOUT is ready
Navid Emamdoost navid.emamdoost@gmail.com Staging: fbtft: fix memory leak in fbtft_framebuffer_alloc
Bartosz Golaszewski bgolaszewski@baylibre.com gpiolib: don't clear FLAG_IS_OUT when emulating open-drain/open-source
Brian Norris briannorris@chromium.org firmware: google: increment VPD key_len properly
Michal Hocko mhocko@suse.com kernel/sysctl.c: do not override max_threads provided by userspace
Pavel Shilovsky piastryyy@gmail.com CIFS: Force reval dentry if LOOKUP_REVAL flag is set
Pavel Shilovsky piastryyy@gmail.com CIFS: Force revalidate inode when dentry is stale
Pavel Shilovsky piastryyy@gmail.com CIFS: Gracefully handle QueryInfo errors during open
Steve MacLean Steve.MacLean@microsoft.com perf inject jit: Fix JIT_CODE_MOVE filename
Ian Rogers irogers@google.com perf llvm: Don't access out-of-scope array
Ard Biesheuvel ard.biesheuvel@linaro.org efivar/ssdt: Don't iterate over EFI vars if no SSDT override was specified
David Frey dpfrey@gmail.com iio: light: opt3001: fix mutex unlock race
Hans de Goede hdegoede@redhat.com iio: adc: axp288: Override TS pin bias current for some models
Marco Felsch m.felsch@pengutronix.de iio: adc: ad799x: fix probe error handling
Navid Emamdoost navid.emamdoost@gmail.com staging: vt6655: Fix memory leak in vt6655_probe
Johan Hovold johan@kernel.org USB: legousbtower: fix use-after-free on release
Johan Hovold johan@kernel.org USB: legousbtower: fix open after failed reset request
Johan Hovold johan@kernel.org USB: legousbtower: fix potential NULL-deref on disconnect
Johan Hovold johan@kernel.org USB: legousbtower: fix deadlock on disconnect
Johan Hovold johan@kernel.org USB: legousbtower: fix slab info leak at probe
Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com usb: renesas_usbhs: gadget: Fix usb_ep_set_{halt,wedge}() behavior
Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com usb: renesas_usbhs: gadget: Do not discard queues in usb_ep_set_{halt,wedge}()
Jacky.Cao@sony.com Jacky.Cao@sony.com USB: dummy-hcd: fix power budget for SuperSpeed mode
Johan Hovold johan@kernel.org USB: microtek: fix info-leak at probe
Johan Hovold johan@kernel.org USB: usblcd: fix I/O after disconnect
Johan Hovold johan@kernel.org USB: serial: fix runtime PM after driver unbind
Reinhard Speyerer rspmn@arcor.de USB: serial: option: add support for Cinterion CLS8 devices
Daniele Palmas dnlplm@gmail.com USB: serial: option: add Telit FN980 compositions
Beni Mahler beni.mahler@gmx.net USB: serial: ftdi_sio: add device IDs for Sienna and Echelon PL-20
Johan Hovold johan@kernel.org USB: serial: keyspan: fix NULL-derefs on open() and write()
Randy Dunlap rdunlap@infradead.org serial: uartlite: fix exit path null pointer
Johan Hovold johan@kernel.org USB: ldusb: fix NULL-derefs on driver unbind
Johan Hovold johan@kernel.org USB: chaoskey: fix use-after-free on release
Johan Hovold johan@kernel.org USB: usblp: fix runtime PM after driver unbind
Johan Hovold johan@kernel.org USB: iowarrior: fix use-after-free after driver unbind
Johan Hovold johan@kernel.org USB: iowarrior: fix use-after-free on release
Johan Hovold johan@kernel.org USB: iowarrior: fix use-after-free on disconnect
Johan Hovold johan@kernel.org USB: adutux: fix use-after-free on release
Johan Hovold johan@kernel.org USB: adutux: fix NULL-derefs on disconnect
Johan Hovold johan@kernel.org USB: adutux: fix use-after-free on disconnect
Colin Ian King colin.king@canonical.com USB: adutux: remove redundant variable minor
Kai-Heng Feng kai.heng.feng@canonical.com xhci: Increase STS_SAVE timeout in xhci_suspend()
Rick Tseng rtseng@nvidia.com usb: xhci: wait for CNR controller not ready bit in xhci resume
Jan Schmidt jan@centricular.com xhci: Check all endpoints for LPM timeout
Mathias Nyman mathias.nyman@linux.intel.com xhci: Prevent device initiated U1/U2 link pm if exit latency is too long
Mathias Nyman mathias.nyman@linux.intel.com xhci: Fix false warning message about wrong bounce buffer write length
Johan Hovold johan@kernel.org USB: usb-skeleton: fix NULL-deref on disconnect
Johan Hovold johan@kernel.org USB: usb-skeleton: fix runtime PM after driver unbind
Johan Hovold johan@kernel.org USB: yurex: fix NULL-derefs on disconnect
Alan Stern stern@rowland.harvard.edu USB: yurex: Don't retry on unexpected errors
Bastien Nocera hadess@hadess.net USB: rio500: Remove Rio 500 kernel driver
Icenowy Zheng icenowy@aosc.io f2fs: use EINVAL for superblock with invalid magic
Will Deacon will@kernel.org panic: ensure preemption is disabled during panic()
-------------
Diffstat:
Documentation/usb/rio.txt | 138 -------- MAINTAINERS | 7 - Makefile | 4 +- arch/arm/configs/badge4_defconfig | 1 - arch/arm/configs/corgi_defconfig | 1 - arch/arm/configs/pxa_defconfig | 1 - arch/arm/configs/s3c2410_defconfig | 1 - arch/arm/configs/spitz_defconfig | 1 - arch/mips/configs/mtx1_defconfig | 1 - arch/mips/configs/rm200_defconfig | 1 - arch/mips/loongson64/Platform | 4 + arch/mips/vdso/Makefile | 1 + arch/x86/include/asm/mwait.h | 2 +- arch/x86/lib/delay.c | 4 +- drivers/firmware/efi/efi.c | 3 + drivers/firmware/google/vpd_decode.c | 2 +- drivers/gpio/gpiolib.c | 27 +- drivers/iio/adc/ad799x.c | 4 +- drivers/iio/adc/axp288_adc.c | 32 ++ drivers/iio/adc/hx711.c | 49 ++- drivers/iio/light/opt3001.c | 6 +- drivers/media/usb/stkwebcam/stk-webcam.c | 3 +- drivers/staging/fbtft/fbtft-core.c | 7 +- drivers/staging/vt6655/device_main.c | 4 +- drivers/tty/serial/uartlite.c | 3 +- drivers/usb/class/usblp.c | 8 +- drivers/usb/gadget/udc/dummy_hcd.c | 3 +- drivers/usb/host/xhci-ring.c | 4 +- drivers/usb/host/xhci.c | 32 +- drivers/usb/image/microtek.c | 4 + drivers/usb/misc/Kconfig | 10 - drivers/usb/misc/Makefile | 1 - drivers/usb/misc/adutux.c | 26 +- drivers/usb/misc/chaoskey.c | 5 +- drivers/usb/misc/iowarrior.c | 16 +- drivers/usb/misc/ldusb.c | 24 +- drivers/usb/misc/legousbtower.c | 58 ++-- drivers/usb/misc/rio500.c | 574 ------------------------------- drivers/usb/misc/rio500_usb.h | 37 -- drivers/usb/misc/usblcd.c | 33 +- drivers/usb/misc/yurex.c | 18 +- drivers/usb/renesas_usbhs/common.h | 1 + drivers/usb/renesas_usbhs/fifo.c | 2 +- drivers/usb/renesas_usbhs/fifo.h | 1 + drivers/usb/renesas_usbhs/mod_gadget.c | 18 +- drivers/usb/renesas_usbhs/pipe.c | 15 + drivers/usb/renesas_usbhs/pipe.h | 1 + drivers/usb/serial/ftdi_sio.c | 3 + drivers/usb/serial/ftdi_sio_ids.h | 9 + drivers/usb/serial/keyspan.c | 4 +- drivers/usb/serial/option.c | 11 + drivers/usb/serial/usb-serial.c | 5 +- drivers/usb/usb-skeleton.c | 15 +- fs/btrfs/tree-log.c | 36 +- fs/cifs/dir.c | 8 +- fs/cifs/file.c | 6 + fs/cifs/inode.c | 4 + fs/f2fs/super.c | 36 +- fs/libfs.c | 134 ++++---- fs/nfs/direct.c | 78 +++-- fs/xfs/xfs_super.c | 10 + kernel/fork.c | 4 +- kernel/panic.c | 1 + kernel/trace/ftrace.c | 27 +- kernel/trace/trace.c | 17 +- kernel/trace/trace_hwlat.c | 4 +- tools/perf/util/jitdump.c | 6 +- tools/perf/util/llvm-utils.c | 6 +- 68 files changed, 567 insertions(+), 1055 deletions(-)
From: Will Deacon will@kernel.org
commit 20bb759a66be52cf4a9ddd17fddaf509e11490cd upstream.
Calling 'panic()' on a kernel with CONFIG_PREEMPT=y can leave the calling CPU in an infinite loop, but with interrupts and preemption enabled. From this state, userspace can continue to be scheduled, despite the system being "dead" as far as the kernel is concerned.
This is easily reproducible on arm64 when booting with "nosmp" on the command line; a couple of shell scripts print out a periodic "Ping" message whilst another triggers a crash by writing to /proc/sysrq-trigger:
| sysrq: Trigger a crash | Kernel panic - not syncing: sysrq triggered crash | CPU: 0 PID: 1 Comm: init Not tainted 5.2.15 #1 | Hardware name: linux,dummy-virt (DT) | Call trace: | dump_backtrace+0x0/0x148 | show_stack+0x14/0x20 | dump_stack+0xa0/0xc4 | panic+0x140/0x32c | sysrq_handle_reboot+0x0/0x20 | __handle_sysrq+0x124/0x190 | write_sysrq_trigger+0x64/0x88 | proc_reg_write+0x60/0xa8 | __vfs_write+0x18/0x40 | vfs_write+0xa4/0x1b8 | ksys_write+0x64/0xf0 | __arm64_sys_write+0x14/0x20 | el0_svc_common.constprop.0+0xb0/0x168 | el0_svc_handler+0x28/0x78 | el0_svc+0x8/0xc | Kernel Offset: disabled | CPU features: 0x0002,24002004 | Memory Limit: none | ---[ end Kernel panic - not syncing: sysrq triggered crash ]--- | Ping 2! | Ping 1! | Ping 1! | Ping 2!
The issue can also be triggered on x86 kernels if CONFIG_SMP=n, otherwise local interrupts are disabled in 'smp_send_stop()'.
Disable preemption in 'panic()' before re-enabling interrupts.
Link: http://lkml.kernel.org/r/20191002123538.22609-1-will@kernel.org Link: https://lore.kernel.org/r/BX1W47JXPMR8.58IYW53H6M5N@dragonstone Signed-off-by: Will Deacon will@kernel.org Reported-by: Xogium contact@xogium.me Reviewed-by: Kees Cook keescook@chromium.org Cc: Russell King linux@armlinux.org.uk Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Ingo Molnar mingo@redhat.com Cc: Petr Mladek pmladek@suse.com Cc: Feng Tang feng.tang@intel.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/panic.c | 1 + 1 file changed, 1 insertion(+)
--- a/kernel/panic.c +++ b/kernel/panic.c @@ -146,6 +146,7 @@ void panic(const char *fmt, ...) * after setting panic_cpu) from invoking panic() again. */ local_irq_disable(); + preempt_disable_notrace();
/* * It's possible to come here directly from a panic-assertion and
From: Icenowy Zheng icenowy@aosc.io
[ Upstream commit 38fb6d0ea34299d97b031ed64fe994158b6f8eb3 ]
The kernel mount_block_root() function expects -EACESS or -EINVAL for a unmountable filesystem when trying to mount the root with different filesystem types.
However, in 5.3-rc1 the behavior when F2FS code cannot find valid block changed to return -EFSCORRUPTED(-EUCLEAN), and this error code makes mount_block_root() fail when trying to probe F2FS.
When the magic number of the superblock mismatches, it has a high probability that it's just not a F2FS. In this case return -EINVAL seems to be a better result, and this return value can make mount_block_root() probing work again.
Return -EINVAL when the superblock has magic mismatch, -EFSCORRUPTED in other cases (the magic matches but the superblock cannot be recognized).
Fixes: 10f966bbf521 ("f2fs: use generic EFSBADCRC/EFSCORRUPTED") Signed-off-by: Icenowy Zheng icenowy@aosc.io Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/super.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 344aa861774bd..e70975ca723b7 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1814,11 +1814,11 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, struct super_block *sb = sbi->sb; unsigned int blocksize;
- if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { + if (le32_to_cpu(raw_super->magic) != F2FS_SUPER_MAGIC) { f2fs_msg(sb, KERN_INFO, "Magic Mismatch, valid(0x%x) - read(0x%x)", F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); - return 1; + return -EINVAL; }
/* Currently, support only 4KB page cache size */ @@ -1826,7 +1826,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, f2fs_msg(sb, KERN_INFO, "Invalid page_cache_size (%lu), supports only 4KB\n", PAGE_SIZE); - return 1; + return -EFSCORRUPTED; }
/* Currently, support only 4KB block size */ @@ -1835,7 +1835,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, f2fs_msg(sb, KERN_INFO, "Invalid blocksize (%u), supports only 4KB\n", blocksize); - return 1; + return -EFSCORRUPTED; }
/* check log blocks per segment */ @@ -1843,7 +1843,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, f2fs_msg(sb, KERN_INFO, "Invalid log blocks per segment (%u)\n", le32_to_cpu(raw_super->log_blocks_per_seg)); - return 1; + return -EFSCORRUPTED; }
/* Currently, support 512/1024/2048/4096 bytes sector size */ @@ -1853,7 +1853,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, F2FS_MIN_LOG_SECTOR_SIZE) { f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize (%u)", le32_to_cpu(raw_super->log_sectorsize)); - return 1; + return -EFSCORRUPTED; } if (le32_to_cpu(raw_super->log_sectors_per_block) + le32_to_cpu(raw_super->log_sectorsize) != @@ -1862,7 +1862,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, "Invalid log sectors per block(%u) log sectorsize(%u)", le32_to_cpu(raw_super->log_sectors_per_block), le32_to_cpu(raw_super->log_sectorsize)); - return 1; + return -EFSCORRUPTED; }
segment_count = le32_to_cpu(raw_super->segment_count); @@ -1878,7 +1878,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, f2fs_msg(sb, KERN_INFO, "Invalid segment count (%u)", segment_count); - return 1; + return -EFSCORRUPTED; }
if (total_sections > segment_count || @@ -1887,35 +1887,35 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, f2fs_msg(sb, KERN_INFO, "Invalid segment/section count (%u, %u x %u)", segment_count, total_sections, segs_per_sec); - return 1; + return -EFSCORRUPTED; }
if ((segment_count / segs_per_sec) < total_sections) { f2fs_msg(sb, KERN_INFO, "Small segment_count (%u < %u * %u)", segment_count, segs_per_sec, total_sections); - return 1; + return -EFSCORRUPTED; }
if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) { f2fs_msg(sb, KERN_INFO, "Wrong segment_count / block_count (%u > %llu)", segment_count, le64_to_cpu(raw_super->block_count)); - return 1; + return -EFSCORRUPTED; }
if (secs_per_zone > total_sections || !secs_per_zone) { f2fs_msg(sb, KERN_INFO, "Wrong secs_per_zone / total_sections (%u, %u)", secs_per_zone, total_sections); - return 1; + return -EFSCORRUPTED; } if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION) { f2fs_msg(sb, KERN_INFO, "Corrupted extension count (%u > %u)", le32_to_cpu(raw_super->extension_count), F2FS_MAX_EXTENSION); - return 1; + return -EFSCORRUPTED; }
if (le32_to_cpu(raw_super->cp_payload) > @@ -1924,7 +1924,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, "Insane cp_payload (%u > %u)", le32_to_cpu(raw_super->cp_payload), blocks_per_seg - F2FS_CP_PACKS); - return 1; + return -EFSCORRUPTED; }
/* check reserved ino info */ @@ -1936,12 +1936,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, le32_to_cpu(raw_super->node_ino), le32_to_cpu(raw_super->meta_ino), le32_to_cpu(raw_super->root_ino)); - return 1; + return -EFSCORRUPTED; }
/* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ if (sanity_check_area_boundary(sbi, bh)) - return 1; + return -EFSCORRUPTED;
return 0; } @@ -2216,11 +2216,11 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, }
/* sanity checking of raw super */ - if (sanity_check_raw_super(sbi, bh)) { + err = sanity_check_raw_super(sbi, bh); + if (err) { f2fs_msg(sb, KERN_ERR, "Can't find valid F2FS filesystem in %dth superblock", block + 1); - err = -EFSCORRUPTED; brelse(bh); continue; }
From: Bastien Nocera hadess@hadess.net
commit 015664d15270a112c2371d812f03f7c579b35a73 upstream.
The Rio500 kernel driver has not been used by Rio500 owners since 2001 not long after the rio500 project added support for a user-space USB stack through the very first versions of usbdevfs and then libusb.
Support for the kernel driver was removed from the upstream utilities in 2008: https://gitlab.freedesktop.org/hadess/rio500/commit/943f624ab721eb8281c28765...
Cc: Cesar Miquel miquel@df.uba.ar Signed-off-by: Bastien Nocera hadess@hadess.net Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/6251c17584d220472ce882a3d9c199c401a51a71.camel@had... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- Documentation/usb/rio.txt | 138 -------- MAINTAINERS | 7 arch/arm/configs/badge4_defconfig | 1 arch/arm/configs/corgi_defconfig | 1 arch/arm/configs/pxa_defconfig | 1 arch/arm/configs/s3c2410_defconfig | 1 arch/arm/configs/spitz_defconfig | 1 arch/mips/configs/mtx1_defconfig | 1 arch/mips/configs/rm200_defconfig | 1 drivers/usb/misc/Kconfig | 10 drivers/usb/misc/Makefile | 1 drivers/usb/misc/rio500.c | 574 ------------------------------------- drivers/usb/misc/rio500_usb.h | 37 -- 13 files changed, 774 deletions(-)
--- a/Documentation/usb/rio.txt +++ /dev/null @@ -1,138 +0,0 @@ -Copyright (C) 1999, 2000 Bruce Tenison -Portions Copyright (C) 1999, 2000 David Nelson -Thanks to David Nelson for guidance and the usage of the scanner.txt -and scanner.c files to model our driver and this informative file. - -Mar. 2, 2000 - -CHANGES - -- Initial Revision - - -OVERVIEW - -This README will address issues regarding how to configure the kernel -to access a RIO 500 mp3 player. -Before I explain how to use this to access the Rio500 please be warned: - -W A R N I N G: --------------- - -Please note that this software is still under development. The authors -are in no way responsible for any damage that may occur, no matter how -inconsequential. - -It seems that the Rio has a problem when sending .mp3 with low batteries. -I suggest when the batteries are low and you want to transfer stuff that you -replace it with a fresh one. In my case, what happened is I lost two 16kb -blocks (they are no longer usable to store information to it). But I don't -know if that's normal or not; it could simply be a problem with the flash -memory. - -In an extreme case, I left my Rio playing overnight and the batteries wore -down to nothing and appear to have corrupted the flash memory. My RIO -needed to be replaced as a result. Diamond tech support is aware of the -problem. Do NOT allow your batteries to wear down to nothing before -changing them. It appears RIO 500 firmware does not handle low battery -power well at all. - -On systems with OHCI controllers, the kernel OHCI code appears to have -power on problems with some chipsets. If you are having problems -connecting to your RIO 500, try turning it on first and then plugging it -into the USB cable. - -Contact information: --------------------- - - The main page for the project is hosted at sourceforge.net in the following - URL: http://rio500.sourceforge.net. You can also go to the project's - sourceforge home page at: http://sourceforge.net/projects/rio500/. - There is also a mailing list: rio500-users@lists.sourceforge.net - -Authors: -------- - -Most of the code was written by Cesar Miquel miquel@df.uba.ar. Keith -Clayton kclayton@jps.net is incharge of the PPC port and making sure -things work there. Bruce Tenison btenison@dibbs.net is adding support -for .fon files and also does testing. The program will mostly sure be -re-written and Pete Ikusz along with the rest will re-design it. I would -also like to thank Tri Nguyen tmn_3022000@hotmail.com who provided use -with some important information regarding the communication with the Rio. - -ADDITIONAL INFORMATION and Userspace tools - -http://rio500.sourceforge.net/ - - -REQUIREMENTS - -A host with a USB port. Ideally, either a UHCI (Intel) or OHCI -(Compaq and others) hardware port should work. - -A Linux development kernel (2.3.x) with USB support enabled or a -backported version to linux-2.2.x. See http://www.linux-usb.org for -more information on accomplishing this. - -A Linux kernel with RIO 500 support enabled. - -'lspci' which is only needed to determine the type of USB hardware -available in your machine. - -CONFIGURATION - -Using `lspci -v`, determine the type of USB hardware available. - - If you see something like: - - USB Controller: ...... - Flags: ..... - I/O ports at .... - - Then you have a UHCI based controller. - - If you see something like: - - USB Controller: ..... - Flags: .... - Memory at ..... - - Then you have a OHCI based controller. - -Using `make menuconfig` or your preferred method for configuring the -kernel, select 'Support for USB', 'OHCI/UHCI' depending on your -hardware (determined from the steps above), 'USB Diamond Rio500 support', and -'Preliminary USB device filesystem'. Compile and install the modules -(you may need to execute `depmod -a` to update the module -dependencies). - -Add a device for the USB rio500: - `mknod /dev/usb/rio500 c 180 64` - -Set appropriate permissions for /dev/usb/rio500 (don't forget about -group and world permissions). Both read and write permissions are -required for proper operation. - -Load the appropriate modules (if compiled as modules): - - OHCI: - modprobe usbcore - modprobe usb-ohci - modprobe rio500 - - UHCI: - modprobe usbcore - modprobe usb-uhci (or uhci) - modprobe rio500 - -That's it. The Rio500 Utils at: http://rio500.sourceforge.net should -be able to access the rio500. - -BUGS - -If you encounter any problems feel free to drop me an email. - -Bruce Tenison -btenison@dibbs.net - --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13886,13 +13886,6 @@ W: http://www.linux-usb.org/usbnet S: Maintained F: drivers/net/usb/dm9601.c
-USB DIAMOND RIO500 DRIVER -M: Cesar Miquel miquel@df.uba.ar -L: rio500-users@lists.sourceforge.net -W: http://rio500.sourceforge.net -S: Maintained -F: drivers/usb/misc/rio500* - USB EHCI DRIVER M: Alan Stern stern@rowland.harvard.edu L: linux-usb@vger.kernel.org --- a/arch/arm/configs/badge4_defconfig +++ b/arch/arm/configs/badge4_defconfig @@ -91,7 +91,6 @@ CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m CONFIG_EXT2_FS=m CONFIG_EXT3_FS=m CONFIG_MSDOS_FS=y --- a/arch/arm/configs/corgi_defconfig +++ b/arch/arm/configs/corgi_defconfig @@ -197,7 +197,6 @@ CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_EMI62=m CONFIG_USB_EMI26=m -CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_CYTHERM=m --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -588,7 +588,6 @@ CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_EMI62=m CONFIG_USB_EMI26=m -CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_CYTHERM=m --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -334,7 +334,6 @@ CONFIG_USB_EMI62=m CONFIG_USB_EMI26=m CONFIG_USB_ADUTUX=m CONFIG_USB_SEVSEG=m -CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_CYPRESS_CY7C63=m --- a/arch/arm/configs/spitz_defconfig +++ b/arch/arm/configs/spitz_defconfig @@ -191,7 +191,6 @@ CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_EMI62=m CONFIG_USB_EMI26=m -CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_CYTHERM=m --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -623,7 +623,6 @@ CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_EMI62=m CONFIG_USB_EMI26=m CONFIG_USB_ADUTUX=m -CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_CYPRESS_CY7C63=m --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -344,7 +344,6 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_CYTHERM=m --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -46,16 +46,6 @@ config USB_SEVSEG To compile this driver as a module, choose M here: the module will be called usbsevseg.
-config USB_RIO500 - tristate "USB Diamond Rio500 support" - help - Say Y here if you want to connect a USB Rio500 mp3 player to your - computer's USB port. Please read file:Documentation/usb/rio.txt - for more information. - - To compile this driver as a module, choose M here: the - module will be called rio500. - config USB_LEGOTOWER tristate "USB Lego Infrared Tower support" help --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_USB_ISIGHTFW) += isight_fi obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_EHSET_TEST_FIXTURE) += ehset.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o --- a/drivers/usb/misc/rio500.c +++ /dev/null @@ -1,574 +0,0 @@ -/* -*- linux-c -*- */ - -/* - * Driver for USB Rio 500 - * - * Cesar Miquel (miquel@df.uba.ar) - * - * based on hp_scanner.c by David E. Nelson (dnelson@jump.net) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). - * - * Changelog: - * 30/05/2003 replaced lock/unlock kernel with up/down - * Daniele Bellucci bellucda@tiscali.it - * */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/sched/signal.h> -#include <linux/mutex.h> -#include <linux/errno.h> -#include <linux/random.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/usb.h> -#include <linux/wait.h> - -#include "rio500_usb.h" - -#define DRIVER_AUTHOR "Cesar Miquel miquel@df.uba.ar" -#define DRIVER_DESC "USB Rio 500 driver" - -#define RIO_MINOR 64 - -/* stall/wait timeout for rio */ -#define NAK_TIMEOUT (HZ) - -#define IBUF_SIZE 0x1000 - -/* Size of the rio buffer */ -#define OBUF_SIZE 0x10000 - -struct rio_usb_data { - struct usb_device *rio_dev; /* init: probe_rio */ - unsigned int ifnum; /* Interface number of the USB device */ - int isopen; /* nz if open */ - int present; /* Device is present on the bus */ - char *obuf, *ibuf; /* transfer buffers */ - char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ - wait_queue_head_t wait_q; /* for timeouts */ - struct mutex lock; /* general race avoidance */ -}; - -static DEFINE_MUTEX(rio500_mutex); -static struct rio_usb_data rio_instance; - -static int open_rio(struct inode *inode, struct file *file) -{ - struct rio_usb_data *rio = &rio_instance; - - /* against disconnect() */ - mutex_lock(&rio500_mutex); - mutex_lock(&(rio->lock)); - - if (rio->isopen || !rio->present) { - mutex_unlock(&(rio->lock)); - mutex_unlock(&rio500_mutex); - return -EBUSY; - } - rio->isopen = 1; - - init_waitqueue_head(&rio->wait_q); - - mutex_unlock(&(rio->lock)); - - dev_info(&rio->rio_dev->dev, "Rio opened.\n"); - mutex_unlock(&rio500_mutex); - - return 0; -} - -static int close_rio(struct inode *inode, struct file *file) -{ - struct rio_usb_data *rio = &rio_instance; - - /* against disconnect() */ - mutex_lock(&rio500_mutex); - mutex_lock(&(rio->lock)); - - rio->isopen = 0; - if (!rio->present) { - /* cleanup has been delayed */ - kfree(rio->ibuf); - kfree(rio->obuf); - rio->ibuf = NULL; - rio->obuf = NULL; - } else { - dev_info(&rio->rio_dev->dev, "Rio closed.\n"); - } - mutex_unlock(&(rio->lock)); - mutex_unlock(&rio500_mutex); - return 0; -} - -static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct RioCommand rio_cmd; - struct rio_usb_data *rio = &rio_instance; - void __user *data; - unsigned char *buffer; - int result, requesttype; - int retries; - int retval=0; - - mutex_lock(&(rio->lock)); - /* Sanity check to make sure rio is connected, powered, etc */ - if (rio->present == 0 || rio->rio_dev == NULL) { - retval = -ENODEV; - goto err_out; - } - - switch (cmd) { - case RIO_RECV_COMMAND: - data = (void __user *) arg; - if (data == NULL) - break; - if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) { - retval = -EFAULT; - goto err_out; - } - if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { - retval = -EINVAL; - goto err_out; - } - buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) { - retval = -ENOMEM; - goto err_out; - } - if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { - retval = -EFAULT; - free_page((unsigned long) buffer); - goto err_out; - } - - requesttype = rio_cmd.requesttype | USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dev_dbg(&rio->rio_dev->dev, - "sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); - /* Send rio control message */ - retries = 3; - while (retries) { - result = usb_control_msg(rio->rio_dev, - usb_rcvctrlpipe(rio-> rio_dev, 0), - rio_cmd.request, - requesttype, - rio_cmd.value, - rio_cmd.index, buffer, - rio_cmd.length, - jiffies_to_msecs(rio_cmd.timeout)); - if (result == -ETIMEDOUT) - retries--; - else if (result < 0) { - dev_err(&rio->rio_dev->dev, - "Error executing ioctrl. code = %d\n", - result); - retries = 0; - } else { - dev_dbg(&rio->rio_dev->dev, - "Executed ioctl. Result = %d (data=%02x)\n", - result, buffer[0]); - if (copy_to_user(rio_cmd.buffer, buffer, - rio_cmd.length)) { - free_page((unsigned long) buffer); - retval = -EFAULT; - goto err_out; - } - retries = 0; - } - - /* rio_cmd.buffer contains a raw stream of single byte - data which has been returned from rio. Data is - interpreted at application level. For data that - will be cast to data types longer than 1 byte, data - will be little_endian and will potentially need to - be swapped at the app level */ - - } - free_page((unsigned long) buffer); - break; - - case RIO_SEND_COMMAND: - data = (void __user *) arg; - if (data == NULL) - break; - if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) { - retval = -EFAULT; - goto err_out; - } - if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { - retval = -EINVAL; - goto err_out; - } - buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) { - retval = -ENOMEM; - goto err_out; - } - if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { - free_page((unsigned long)buffer); - retval = -EFAULT; - goto err_out; - } - - requesttype = rio_cmd.requesttype | USB_DIR_OUT | - USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dev_dbg(&rio->rio_dev->dev, - "sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); - /* Send rio control message */ - retries = 3; - while (retries) { - result = usb_control_msg(rio->rio_dev, - usb_sndctrlpipe(rio-> rio_dev, 0), - rio_cmd.request, - requesttype, - rio_cmd.value, - rio_cmd.index, buffer, - rio_cmd.length, - jiffies_to_msecs(rio_cmd.timeout)); - if (result == -ETIMEDOUT) - retries--; - else if (result < 0) { - dev_err(&rio->rio_dev->dev, - "Error executing ioctrl. code = %d\n", - result); - retries = 0; - } else { - dev_dbg(&rio->rio_dev->dev, - "Executed ioctl. Result = %d\n", result); - retries = 0; - - } - - } - free_page((unsigned long) buffer); - break; - - default: - retval = -ENOTTY; - break; - } - - -err_out: - mutex_unlock(&(rio->lock)); - return retval; -} - -static ssize_t -write_rio(struct file *file, const char __user *buffer, - size_t count, loff_t * ppos) -{ - DEFINE_WAIT(wait); - struct rio_usb_data *rio = &rio_instance; - - unsigned long copy_size; - unsigned long bytes_written = 0; - unsigned int partial; - - int result = 0; - int maxretry; - int errn = 0; - int intr; - - intr = mutex_lock_interruptible(&(rio->lock)); - if (intr) - return -EINTR; - /* Sanity check to make sure rio is connected, powered, etc */ - if (rio->present == 0 || rio->rio_dev == NULL) { - mutex_unlock(&(rio->lock)); - return -ENODEV; - } - - - - do { - unsigned long thistime; - char *obuf = rio->obuf; - - thistime = copy_size = - (count >= OBUF_SIZE) ? OBUF_SIZE : count; - if (copy_from_user(rio->obuf, buffer, copy_size)) { - errn = -EFAULT; - goto error; - } - maxretry = 5; - while (thistime) { - if (!rio->rio_dev) { - errn = -ENODEV; - goto error; - } - if (signal_pending(current)) { - mutex_unlock(&(rio->lock)); - return bytes_written ? bytes_written : -EINTR; - } - - result = usb_bulk_msg(rio->rio_dev, - usb_sndbulkpipe(rio->rio_dev, 2), - obuf, thistime, &partial, 5000); - - dev_dbg(&rio->rio_dev->dev, - "write stats: result:%d thistime:%lu partial:%u\n", - result, thistime, partial); - - if (result == -ETIMEDOUT) { /* NAK - so hold for a while */ - if (!maxretry--) { - errn = -ETIME; - goto error; - } - prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); - schedule_timeout(NAK_TIMEOUT); - finish_wait(&rio->wait_q, &wait); - continue; - } else if (!result && partial) { - obuf += partial; - thistime -= partial; - } else - break; - } - if (result) { - dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n", - result); - errn = -EIO; - goto error; - } - bytes_written += copy_size; - count -= copy_size; - buffer += copy_size; - } while (count > 0); - - mutex_unlock(&(rio->lock)); - - return bytes_written ? bytes_written : -EIO; - -error: - mutex_unlock(&(rio->lock)); - return errn; -} - -static ssize_t -read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) -{ - DEFINE_WAIT(wait); - struct rio_usb_data *rio = &rio_instance; - ssize_t read_count; - unsigned int partial; - int this_read; - int result; - int maxretry = 10; - char *ibuf; - int intr; - - intr = mutex_lock_interruptible(&(rio->lock)); - if (intr) - return -EINTR; - /* Sanity check to make sure rio is connected, powered, etc */ - if (rio->present == 0 || rio->rio_dev == NULL) { - mutex_unlock(&(rio->lock)); - return -ENODEV; - } - - ibuf = rio->ibuf; - - read_count = 0; - - - while (count > 0) { - if (signal_pending(current)) { - mutex_unlock(&(rio->lock)); - return read_count ? read_count : -EINTR; - } - if (!rio->rio_dev) { - mutex_unlock(&(rio->lock)); - return -ENODEV; - } - this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; - - result = usb_bulk_msg(rio->rio_dev, - usb_rcvbulkpipe(rio->rio_dev, 1), - ibuf, this_read, &partial, - 8000); - - dev_dbg(&rio->rio_dev->dev, - "read stats: result:%d this_read:%u partial:%u\n", - result, this_read, partial); - - if (partial) { - count = this_read = partial; - } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ - if (!maxretry--) { - mutex_unlock(&(rio->lock)); - dev_err(&rio->rio_dev->dev, - "read_rio: maxretry timeout\n"); - return -ETIME; - } - prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); - schedule_timeout(NAK_TIMEOUT); - finish_wait(&rio->wait_q, &wait); - continue; - } else if (result != -EREMOTEIO) { - mutex_unlock(&(rio->lock)); - dev_err(&rio->rio_dev->dev, - "Read Whoops - result:%d partial:%u this_read:%u\n", - result, partial, this_read); - return -EIO; - } else { - mutex_unlock(&(rio->lock)); - return (0); - } - - if (this_read) { - if (copy_to_user(buffer, ibuf, this_read)) { - mutex_unlock(&(rio->lock)); - return -EFAULT; - } - count -= this_read; - read_count += this_read; - buffer += this_read; - } - } - mutex_unlock(&(rio->lock)); - return read_count; -} - -static const struct file_operations usb_rio_fops = { - .owner = THIS_MODULE, - .read = read_rio, - .write = write_rio, - .unlocked_ioctl = ioctl_rio, - .open = open_rio, - .release = close_rio, - .llseek = noop_llseek, -}; - -static struct usb_class_driver usb_rio_class = { - .name = "rio500%d", - .fops = &usb_rio_fops, - .minor_base = RIO_MINOR, -}; - -static int probe_rio(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct rio_usb_data *rio = &rio_instance; - int retval = 0; - - mutex_lock(&rio500_mutex); - if (rio->present) { - dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); - retval = -EBUSY; - goto bail_out; - } else { - dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); - } - - retval = usb_register_dev(intf, &usb_rio_class); - if (retval) { - dev_err(&dev->dev, - "Not able to get a minor for this device.\n"); - retval = -ENOMEM; - goto bail_out; - } - - rio->rio_dev = dev; - - if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) { - dev_err(&dev->dev, - "probe_rio: Not enough memory for the output buffer\n"); - usb_deregister_dev(intf, &usb_rio_class); - retval = -ENOMEM; - goto bail_out; - } - dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); - - if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) { - dev_err(&dev->dev, - "probe_rio: Not enough memory for the input buffer\n"); - usb_deregister_dev(intf, &usb_rio_class); - kfree(rio->obuf); - retval = -ENOMEM; - goto bail_out; - } - dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); - - mutex_init(&(rio->lock)); - - usb_set_intfdata (intf, rio); - rio->present = 1; -bail_out: - mutex_unlock(&rio500_mutex); - - return retval; -} - -static void disconnect_rio(struct usb_interface *intf) -{ - struct rio_usb_data *rio = usb_get_intfdata (intf); - - usb_set_intfdata (intf, NULL); - mutex_lock(&rio500_mutex); - if (rio) { - usb_deregister_dev(intf, &usb_rio_class); - - mutex_lock(&(rio->lock)); - if (rio->isopen) { - rio->isopen = 0; - /* better let it finish - the release will do whats needed */ - rio->rio_dev = NULL; - mutex_unlock(&(rio->lock)); - mutex_unlock(&rio500_mutex); - return; - } - kfree(rio->ibuf); - kfree(rio->obuf); - - dev_info(&intf->dev, "USB Rio disconnected.\n"); - - rio->present = 0; - mutex_unlock(&(rio->lock)); - } - mutex_unlock(&rio500_mutex); -} - -static const struct usb_device_id rio_table[] = { - { USB_DEVICE(0x0841, 1) }, /* Rio 500 */ - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, rio_table); - -static struct usb_driver rio_driver = { - .name = "rio500", - .probe = probe_rio, - .disconnect = disconnect_rio, - .id_table = rio_table, -}; - -module_usb_driver(rio_driver); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); - --- a/drivers/usb/misc/rio500_usb.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ---------------------------------------------------------------------- - - Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - ---------------------------------------------------------------------- */ - - - -#define RIO_SEND_COMMAND 0x1 -#define RIO_RECV_COMMAND 0x2 - -#define RIO_DIR_OUT 0x0 -#define RIO_DIR_IN 0x1 - -struct RioCommand { - short length; - int request; - int requesttype; - int value; - int index; - void __user *buffer; - int timeout; -};
From: Alan Stern stern@rowland.harvard.edu
commit 32a0721c6620b77504916dac0cea8ad497c4878a upstream.
According to Greg KH, it has been generally agreed that when a USB driver encounters an unknown error (or one it can't handle directly), it should just give up instead of going into a potentially infinite retry loop.
The three codes -EPROTO, -EILSEQ, and -ETIME fall into this category. They can be caused by bus errors such as packet loss or corruption, attempting to communicate with a disconnected device, or by malicious firmware. Nowadays the extent of packet loss or corruption is negligible, so it should be safe for a driver to give up whenever one of these errors occurs.
Although the yurex driver handles -EILSEQ errors in this way, it doesn't do the same for -EPROTO (as discovered by the syzbot fuzzer) or other unrecognized errors. This patch adjusts the driver so that it doesn't log an error message for -EPROTO or -ETIME, and it doesn't retry after any errors.
Reported-and-tested-by: syzbot+b24d736f18a1541ad550@syzkaller.appspotmail.com Signed-off-by: Alan Stern stern@rowland.harvard.edu CC: Tomoki Sekiyama tomoki.sekiyama@gmail.com CC: stable@vger.kernel.org Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1909171245410.1590-100000@iolanthe... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/yurex.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -136,6 +136,7 @@ static void yurex_interrupt(struct urb * switch (status) { case 0: /*success*/ break; + /* The device is terminated or messed up, give up */ case -EOVERFLOW: dev_err(&dev->interface->dev, "%s - overflow with length %d, actual length is %d\n", @@ -144,12 +145,13 @@ static void yurex_interrupt(struct urb * case -ENOENT: case -ESHUTDOWN: case -EILSEQ: - /* The device is terminated, clean up */ + case -EPROTO: + case -ETIME: return; default: dev_err(&dev->interface->dev, "%s - unknown status received: %d\n", __func__, status); - goto exit; + return; }
/* handle received message */ @@ -181,7 +183,6 @@ static void yurex_interrupt(struct urb * break; }
-exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); if (retval) { dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n",
From: Johan Hovold johan@kernel.org
commit aafb00a977cf7d81821f7c9d12e04c558c22dc3c upstream.
The driver was using its struct usb_interface pointer as an inverted disconnected flag, but was setting it to NULL without making sure all code paths that used it were done with it.
Before commit ef61eb43ada6 ("USB: yurex: Fix protection fault after device removal") this included the interrupt-in completion handler, but there are further accesses in dev_err and dev_dbg statements in yurex_write() and the driver-data destructor (sic!).
Fix this by unconditionally stopping also the control URB at disconnect and by using a dedicated disconnected flag.
Note that we need to take a reference to the struct usb_interface to avoid a use-after-free in the destructor whenever the device was disconnected while the character device was still open.
Fixes: aadd6472d904 ("USB: yurex.c: remove dbg() usage") Fixes: 45714104b9e8 ("USB: yurex.c: remove err() usage") Cc: stable stable@vger.kernel.org # 3.5: ef61eb43ada6 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009153848.8664-6-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/yurex.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -64,6 +64,7 @@ struct usb_yurex {
struct kref kref; struct mutex io_mutex; + unsigned long disconnected:1; struct fasync_struct *async_queue; wait_queue_head_t waitq;
@@ -111,6 +112,7 @@ static void yurex_delete(struct kref *kr dev->int_buffer, dev->urb->transfer_dma); usb_free_urb(dev->urb); } + usb_put_intf(dev->interface); usb_put_dev(dev->udev); kfree(dev); } @@ -209,7 +211,7 @@ static int yurex_probe(struct usb_interf init_waitqueue_head(&dev->waitq);
dev->udev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; + dev->interface = usb_get_intf(interface);
/* set up the endpoint information */ iface_desc = interface->cur_altsetting; @@ -320,8 +322,9 @@ static void yurex_disconnect(struct usb_
/* prevent more I/O from starting */ usb_poison_urb(dev->urb); + usb_poison_urb(dev->cntl_urb); mutex_lock(&dev->io_mutex); - dev->interface = NULL; + dev->disconnected = 1; mutex_unlock(&dev->io_mutex);
/* wakeup waiters */ @@ -409,7 +412,7 @@ static ssize_t yurex_read(struct file *f dev = file->private_data;
mutex_lock(&dev->io_mutex); - if (!dev->interface) { /* already disconnected */ + if (dev->disconnected) { /* already disconnected */ mutex_unlock(&dev->io_mutex); return -ENODEV; } @@ -444,7 +447,7 @@ static ssize_t yurex_write(struct file * goto error;
mutex_lock(&dev->io_mutex); - if (!dev->interface) { /* already disconnected */ + if (dev->disconnected) { /* already disconnected */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto error;
From: Johan Hovold johan@kernel.org
commit 5c290a5e42c3387e82de86965784d30e6c5270fd upstream.
Since commit c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") USB drivers must always balance their runtime PM gets and puts, including when the driver has already been unbound from the interface.
Leaving the interface with a positive PM usage counter would prevent a later bound driver from suspending the device.
Fixes: c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191001084908.2003-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/usb-skeleton.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -75,6 +75,7 @@ static void skel_delete(struct kref *kre struct usb_skel *dev = to_skel_dev(kref);
usb_free_urb(dev->bulk_in_urb); + usb_put_intf(dev->interface); usb_put_dev(dev->udev); kfree(dev->bulk_in_buffer); kfree(dev); @@ -126,10 +127,7 @@ static int skel_release(struct inode *in return -ENODEV;
/* allow the device to be autosuspended */ - mutex_lock(&dev->io_mutex); - if (dev->interface) - usb_autopm_put_interface(dev->interface); - mutex_unlock(&dev->io_mutex); + usb_autopm_put_interface(dev->interface);
/* decrement the count on our device */ kref_put(&dev->kref, skel_delete); @@ -507,7 +505,7 @@ static int skel_probe(struct usb_interfa init_waitqueue_head(&dev->bulk_in_wait);
dev->udev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; + dev->interface = usb_get_intf(interface);
/* set up the endpoint information */ /* use only the first bulk-in and bulk-out endpoints */
From: Johan Hovold johan@kernel.org
commit bed5ef230943863b9abf5eae226a20fad9a8ff71 upstream.
The driver was using its struct usb_interface pointer as an inverted disconnected flag and was setting it to NULL before making sure all completion handlers had run. This could lead to NULL-pointer dereferences in the dev_err() statements in the completion handlers which relies on said pointer.
Fix this by using a dedicated disconnected flag.
Note that this is also addresses a NULL-pointer dereference at release() and a struct usb_interface reference leak introduced by a recent runtime PM fix, which depends on and should have been submitted together with this patch.
Fixes: 4212cd74ca6f ("USB: usb-skeleton.c: remove err() usage") Fixes: 5c290a5e42c3 ("USB: usb-skeleton: fix runtime PM after driver unbind") Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009170944.30057-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/usb-skeleton.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -63,6 +63,7 @@ struct usb_skel { spinlock_t err_lock; /* lock for errors */ struct kref kref; struct mutex io_mutex; /* synchronize I/O with disconnect */ + unsigned long disconnected:1; wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */ }; #define to_skel_dev(d) container_of(d, struct usb_skel, kref) @@ -239,7 +240,7 @@ static ssize_t skel_read(struct file *fi if (rv < 0) return rv;
- if (!dev->interface) { /* disconnect() was called */ + if (dev->disconnected) { /* disconnect() was called */ rv = -ENODEV; goto exit; } @@ -420,7 +421,7 @@ static ssize_t skel_write(struct file *f
/* this lock makes sure we don't submit URBs to gone devices */ mutex_lock(&dev->io_mutex); - if (!dev->interface) { /* disconnect() was called */ + if (dev->disconnected) { /* disconnect() was called */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto error; @@ -571,7 +572,7 @@ static void skel_disconnect(struct usb_i
/* prevent more I/O from starting */ mutex_lock(&dev->io_mutex); - dev->interface = NULL; + dev->disconnected = 1; mutex_unlock(&dev->io_mutex);
usb_kill_anchored_urbs(&dev->submitted);
From: Mathias Nyman mathias.nyman@linux.intel.com
commit c03101ff4f74bb30679c1a03d551ecbef1024bf6 upstream.
The check printing out the "WARN Wrong bounce buffer write length:" uses incorrect values when comparing bytes written from scatterlist to bounce buffer. Actual copied lengths are fine.
The used seg->bounce_len will be set to equal new_buf_len a few lines later in the code, but is incorrect when doing the comparison.
The patch which added this false warning was backported to 4.8+ kernels so this should be backported as far as well.
Cc: stable@vger.kernel.org # v4.8+ Fixes: 597c56e372da ("xhci: update bounce buffer with correct sg num") Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/1570190373-30684-2-git-send-email-mathias.nyman@li... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/host/xhci-ring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3223,10 +3223,10 @@ static int xhci_align_td(struct xhci_hcd if (usb_urb_dir_out(urb)) { len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs, seg->bounce_buf, new_buff_len, enqd_len); - if (len != seg->bounce_len) + if (len != new_buff_len) xhci_warn(xhci, "WARN Wrong bounce buffer write length: %zu != %d\n", - len, seg->bounce_len); + len, new_buff_len); seg->bounce_dma = dma_map_single(dev, seg->bounce_buf, max_pkt, DMA_TO_DEVICE); } else {
From: Mathias Nyman mathias.nyman@linux.intel.com
commit cd9d9491e835a845c1a98b8471f88d26285e0bb9 upstream.
If host/hub initiated link pm is prevented by a driver flag we still must ensure that periodic endpoints have longer service intervals than link pm exit latency before allowing device initiated link pm.
Fix this by continue walking and checking endpoint service interval if xhci_get_timeout_no_hub_lpm() returns anything else than USB3_LPM_DISABLED
While at it fix the split line error message
Tested-by: Jan Schmidt jan@centricular.com Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/1570190373-30684-3-git-send-email-mathias.nyman@li... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/host/xhci.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4607,10 +4607,12 @@ static u16 xhci_calculate_lpm_timeout(st if (intf->dev.driver) { driver = to_usb_driver(intf->dev.driver); if (driver && driver->disable_hub_initiated_lpm) { - dev_dbg(&udev->dev, "Hub-initiated %s disabled " - "at request of driver %s\n", - state_name, driver->name); - return xhci_get_timeout_no_hub_lpm(udev, state); + dev_dbg(&udev->dev, "Hub-initiated %s disabled at request of driver %s\n", + state_name, driver->name); + timeout = xhci_get_timeout_no_hub_lpm(udev, + state); + if (timeout == USB3_LPM_DISABLED) + return timeout; } }
From: Jan Schmidt jan@centricular.com
commit d500c63f80f2ea08ee300e57da5f2af1c13875f5 upstream.
If an endpoint is encountered that returns USB3_LPM_DEVICE_INITIATED, keep checking further endpoints, as there might be periodic endpoints later that return USB3_LPM_DISABLED due to shorter service intervals.
Without this, the code can set too high a maximum-exit-latency and prevent the use of multiple USB3 cameras that should be able to work.
Cc: stable@vger.kernel.org Signed-off-by: Jan Schmidt jan@centricular.com Tested-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/1570190373-30684-4-git-send-email-mathias.nyman@li... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/host/xhci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4491,12 +4491,12 @@ static int xhci_update_timeout_for_endpo alt_timeout = xhci_call_host_update_timeout_for_endpoint(xhci, udev, desc, state, timeout);
- /* If we found we can't enable hub-initiated LPM, or + /* If we found we can't enable hub-initiated LPM, and * the U1 or U2 exit latency was too high to allow - * device-initiated LPM as well, just stop searching. + * device-initiated LPM as well, then we will disable LPM + * for this device, so stop searching any further. */ - if (alt_timeout == USB3_LPM_DISABLED || - alt_timeout == USB3_LPM_DEVICE_INITIATED) { + if (alt_timeout == USB3_LPM_DISABLED) { *timeout = alt_timeout; return -E2BIG; }
From: Rick Tseng rtseng@nvidia.com
commit a70bcbc322837eda1ab5994d12db941dc9733a7d upstream.
NVIDIA 3.1 xHCI card would lose power when moving power state into D3Cold. Thus we need to wait for CNR bit to clear in xhci resume, just as in xhci init.
[Minor changes to comment and commit message -Mathias] Cc: stable@vger.kernel.org Signed-off-by: Rick Tseng rtseng@nvidia.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/1570190373-30684-6-git-send-email-mathias.nyman@li... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/host/xhci.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
--- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1044,6 +1044,18 @@ int xhci_resume(struct xhci_hcd *xhci, b hibernated = true;
if (!hibernated) { + /* + * Some controllers might lose power during suspend, so wait + * for controller not ready bit to clear, just as in xHC init. + */ + retval = xhci_handshake(&xhci->op_regs->status, + STS_CNR, 0, 10 * 1000 * 1000); + if (retval) { + xhci_warn(xhci, "Controller not ready at resume %d\n", + retval); + spin_unlock_irq(&xhci->lock); + return retval; + } /* step 1: restore register */ xhci_restore_registers(xhci); /* step 2: initialize command ring buffer */
From: Kai-Heng Feng kai.heng.feng@canonical.com
commit ac343366846a445bb81f0a0e8f16abb8bd5d5d88 upstream.
After commit f7fac17ca925 ("xhci: Convert xhci_handshake() to use readl_poll_timeout_atomic()"), ASMedia xHCI may fail to suspend.
Although the algorithms are essentially the same, the old max timeout is (usec + usec * time of doing readl()), and the new max timeout is just usec, which is much less than the old one.
Increase the timeout to make ASMedia xHCI able to suspend again.
BugLink: https://bugs.launchpad.net/bugs/1844021 Fixes: f7fac17ca925 ("xhci: Convert xhci_handshake() to use readl_poll_timeout_atomic()") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/1570190373-30684-8-git-send-email-mathias.nyman@li... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -968,7 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, writel(command, &xhci->op_regs->command); xhci->broken_suspend = 0; if (xhci_handshake(&xhci->op_regs->status, - STS_SAVE, 0, 10 * 1000)) { + STS_SAVE, 0, 20 * 1000)) { /* * AMD SNPS xHC 3.0 occasionally does not clear the * SSS bit of USBSTS and when driver tries to poll
From: Colin Ian King colin.king@canonical.com
commit 8444efc4a052332d643ed5c8aebcca148c7de032 upstream.
Variable minor is being assigned but never read, hence it is redundant and can be removed. Cleans up clang warning:
drivers/usb/misc/adutux.c:770:2: warning: Value stored to 'minor' is never read
Signed-off-by: Colin Ian King colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/adutux.c | 2 -- 1 file changed, 2 deletions(-)
--- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -761,13 +761,11 @@ error: static void adu_disconnect(struct usb_interface *interface) { struct adu_device *dev; - int minor;
dev = usb_get_intfdata(interface);
mutex_lock(&dev->mtx); /* not interruptible */ dev->udev = NULL; /* poison */ - minor = dev->minor; usb_deregister_dev(interface, &adu_class); mutex_unlock(&dev->mtx);
From: Johan Hovold johan@kernel.org
commit 44efc269db7929f6275a1fa927ef082e533ecde0 upstream.
The driver was clearing its struct usb_device pointer, which it used as an inverted disconnected flag, before deregistering the character device and without serialising against racing release().
This could lead to a use-after-free if a racing release() callback observes the cleared pointer and frees the driver data before disconnect() is finished with it.
This could also lead to NULL-pointer dereferences in a racing open().
Fixes: f08812d5eb8f ("USB: FIx locks and urb->status in adutux (updated)") Cc: stable stable@vger.kernel.org # 2.6.24 Reported-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com Tested-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20190925092913.8608-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/adutux.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -764,14 +764,15 @@ static void adu_disconnect(struct usb_in
dev = usb_get_intfdata(interface);
- mutex_lock(&dev->mtx); /* not interruptible */ - dev->udev = NULL; /* poison */ usb_deregister_dev(interface, &adu_class); - mutex_unlock(&dev->mtx);
mutex_lock(&adutux_mutex); usb_set_intfdata(interface, NULL);
+ mutex_lock(&dev->mtx); /* not interruptible */ + dev->udev = NULL; /* poison */ + mutex_unlock(&dev->mtx); + /* if the device is not opened, then we clean up right now */ if (!dev->open_count) adu_delete(dev);
From: Johan Hovold johan@kernel.org
commit b2fa7baee744fde746c17bc1860b9c6f5c2eebb7 upstream.
The driver was using its struct usb_device pointer as an inverted disconnected flag, but was setting it to NULL before making sure all completion handlers had run. This could lead to a NULL-pointer dereference in a number of dev_dbg statements in the completion handlers which relies on said pointer.
The pointer was also dereferenced unconditionally in a dev_dbg statement release() something which would lead to a NULL-deref whenever a device was disconnected before the final character-device close if debugging was enabled.
Fix this by unconditionally stopping all I/O and preventing resubmissions by poisoning the interrupt URBs at disconnect and using a dedicated disconnected flag.
This also makes sure that all I/O has completed by the time the disconnect callback returns.
Fixes: 1ef37c6047fe ("USB: adutux: remove custom debug macro and module parameter") Fixes: 66d4bc30d128 ("USB: adutux: remove custom debug macro") Cc: stable stable@vger.kernel.org # 3.12 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20190925092913.8608-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/adutux.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
--- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -79,6 +79,7 @@ struct adu_device { char serial_number[8];
int open_count; /* number of times this port has been opened */ + unsigned long disconnected:1;
char *read_buffer_primary; int read_buffer_length; @@ -120,7 +121,7 @@ static void adu_abort_transfers(struct a { unsigned long flags;
- if (dev->udev == NULL) + if (dev->disconnected) return;
/* shutdown transfer */ @@ -243,7 +244,7 @@ static int adu_open(struct inode *inode, }
dev = usb_get_intfdata(interface); - if (!dev || !dev->udev) { + if (!dev) { retval = -ENODEV; goto exit_no_device; } @@ -326,7 +327,7 @@ static int adu_release(struct inode *ino }
adu_release_internal(dev); - if (dev->udev == NULL) { + if (dev->disconnected) { /* the device was unplugged before the file was released */ if (!dev->open_count) /* ... and we're the last user */ adu_delete(dev); @@ -355,7 +356,7 @@ static ssize_t adu_read(struct file *fil return -ERESTARTSYS;
/* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; pr_err("No device or device unplugged %d\n", retval); goto exit; @@ -520,7 +521,7 @@ static ssize_t adu_write(struct file *fi goto exit_nolock;
/* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; pr_err("No device or device unplugged %d\n", retval); goto exit; @@ -766,11 +767,14 @@ static void adu_disconnect(struct usb_in
usb_deregister_dev(interface, &adu_class);
+ usb_poison_urb(dev->interrupt_in_urb); + usb_poison_urb(dev->interrupt_out_urb); + mutex_lock(&adutux_mutex); usb_set_intfdata(interface, NULL);
mutex_lock(&dev->mtx); /* not interruptible */ - dev->udev = NULL; /* poison */ + dev->disconnected = 1; mutex_unlock(&dev->mtx);
/* if the device is not opened, then we clean up right now */
From: Johan Hovold johan@kernel.org
commit 123a0f125fa3d2104043697baa62899d9e549272 upstream.
The driver was accessing its struct usb_device in its release() callback without holding a reference. This would lead to a use-after-free whenever the device was disconnected while the character device was still open.
Fixes: 66d4bc30d128 ("USB: adutux: remove custom debug macro") Cc: stable stable@vger.kernel.org # 3.12 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009153848.8664-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/adutux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -151,6 +151,7 @@ static void adu_delete(struct adu_device kfree(dev->read_buffer_secondary); kfree(dev->interrupt_in_buffer); kfree(dev->interrupt_out_buffer); + usb_put_dev(dev->udev); kfree(dev); }
@@ -666,7 +667,7 @@ static int adu_probe(struct usb_interfac
mutex_init(&dev->mtx); spin_lock_init(&dev->buflock); - dev->udev = udev; + dev->udev = usb_get_dev(udev); init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->write_wait);
From: Johan Hovold johan@kernel.org
commit edc4746f253d907d048de680a621e121517f484b upstream.
A recent fix addressing a deadlock on disconnect introduced a new bug by moving the present flag out of the critical section protected by the driver-data mutex. This could lead to a racing release() freeing the driver data before disconnect() is done with it.
Due to insufficient locking a related use-after-free could be triggered also before the above mentioned commit. Specifically, the driver needs to hold the driver-data mutex also while checking the opened flag at disconnect().
Fixes: c468a8aa790e ("usb: iowarrior: fix deadlock on disconnect") Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") Cc: stable stable@vger.kernel.org # 2.6.21 Reported-by: syzbot+0761012cebf7bdb38137@syzkaller.appspotmail.com Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009104846.5925-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/iowarrior.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
--- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -870,8 +870,6 @@ static void iowarrior_disconnect(struct dev = usb_get_intfdata(interface); mutex_lock(&iowarrior_open_disc_lock); usb_set_intfdata(interface, NULL); - /* prevent device read, write and ioctl */ - dev->present = 0;
minor = dev->minor; mutex_unlock(&iowarrior_open_disc_lock); @@ -882,8 +880,7 @@ static void iowarrior_disconnect(struct mutex_lock(&dev->mutex);
/* prevent device read, write and ioctl */ - - mutex_unlock(&dev->mutex); + dev->present = 0;
if (dev->opened) { /* There is a process that holds a filedescriptor to the device , @@ -893,8 +890,10 @@ static void iowarrior_disconnect(struct usb_kill_urb(dev->int_in_urb); wake_up_interruptible(&dev->read_wait); wake_up_interruptible(&dev->write_wait); + mutex_unlock(&dev->mutex); } else { /* no process is using the device, cleanup now */ + mutex_unlock(&dev->mutex); iowarrior_delete(dev); }
From: Johan Hovold johan@kernel.org
commit 80cd5479b525093a56ef768553045741af61b250 upstream.
The driver was accessing its struct usb_interface from its release() callback without holding a reference. This would lead to a use-after-free whenever debugging was enabled and the device was disconnected while its character device was open.
Fixes: 549e83500b80 ("USB: iowarrior: Convert local dbg macro to dev_dbg") Cc: stable stable@vger.kernel.org # 3.16 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009104846.5925-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/iowarrior.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -246,6 +246,7 @@ static inline void iowarrior_delete(stru kfree(dev->int_in_buffer); usb_free_urb(dev->int_in_urb); kfree(dev->read_queue); + usb_put_intf(dev->interface); kfree(dev); }
@@ -768,7 +769,7 @@ static int iowarrior_probe(struct usb_in init_waitqueue_head(&dev->write_wait);
dev->udev = udev; - dev->interface = interface; + dev->interface = usb_get_intf(interface);
iface_desc = interface->cur_altsetting; dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
From: Johan Hovold johan@kernel.org
commit b5f8d46867ca233d773408ffbe691a8062ed718f upstream.
Make sure to stop also the asynchronous write URBs on disconnect() to avoid use-after-free in the completion handler after driver unbind.
Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") Cc: stable stable@vger.kernel.org # 2.6.21: 51a2f077c44e ("USB: introduce usb_anchor") Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009104846.5925-4-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/iowarrior.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -87,6 +87,7 @@ struct iowarrior { char chip_serial[9]; /* the serial number string of the chip connected */ int report_size; /* number of bytes in a report */ u16 product_id; + struct usb_anchor submitted; };
/*--------------*/ @@ -428,11 +429,13 @@ static ssize_t iowarrior_write(struct fi retval = -EFAULT; goto error; } + usb_anchor_urb(int_out_urb, &dev->submitted); retval = usb_submit_urb(int_out_urb, GFP_KERNEL); if (retval) { dev_dbg(&dev->interface->dev, "submit error %d for urb nr.%d\n", retval, atomic_read(&dev->write_busy)); + usb_unanchor_urb(int_out_urb); goto error; } /* submit was ok */ @@ -774,6 +777,8 @@ static int iowarrior_probe(struct usb_in iface_desc = interface->cur_altsetting; dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
+ init_usb_anchor(&dev->submitted); + res = usb_find_last_int_in_endpoint(iface_desc, &dev->int_in_endpoint); if (res) { dev_err(&interface->dev, "no interrupt-in endpoint found\n"); @@ -889,6 +894,7 @@ static void iowarrior_disconnect(struct Deleting the device is postponed until close() was called. */ usb_kill_urb(dev->int_in_urb); + usb_kill_anchored_urbs(&dev->submitted); wake_up_interruptible(&dev->read_wait); wake_up_interruptible(&dev->write_wait); mutex_unlock(&dev->mutex);
From: Johan Hovold johan@kernel.org
commit 9a31535859bfd8d1c3ed391f5e9247cd87bb7909 upstream.
Since commit c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") USB drivers must always balance their runtime PM gets and puts, including when the driver has already been unbound from the interface.
Leaving the interface with a positive PM usage counter would prevent a later bound driver from suspending the device.
Fixes: c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191001084908.2003-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/class/usblp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -474,10 +474,12 @@ static int usblp_release(struct inode *i
mutex_lock(&usblp_mutex); usblp->used = 0; - if (usblp->present) { + if (usblp->present) usblp_unlink_urbs(usblp); - usb_autopm_put_interface(usblp->intf); - } else /* finish cleanup from disconnect */ + + usb_autopm_put_interface(usblp->intf); + + if (!usblp->present) /* finish cleanup from disconnect */ usblp_cleanup(usblp); mutex_unlock(&usblp_mutex); return 0;
From: Johan Hovold johan@kernel.org
commit 93ddb1f56ae102f14f9e46a9a9c8017faa970003 upstream.
The driver was accessing its struct usb_interface in its release() callback without holding a reference. This would lead to a use-after-free whenever the device was disconnected while the character device was still open.
Fixes: 66e3e591891d ("usb: Add driver for Altus Metrum ChaosKey device (v2)") Cc: stable stable@vger.kernel.org # 4.1 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009153848.8664-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/chaoskey.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c @@ -106,6 +106,7 @@ static void chaoskey_free(struct chaoske usb_free_urb(dev->urb); kfree(dev->name); kfree(dev->buf); + usb_put_intf(dev->interface); kfree(dev); } } @@ -153,6 +154,8 @@ static int chaoskey_probe(struct usb_int if (dev == NULL) goto out;
+ dev->interface = usb_get_intf(interface); + dev->buf = kmalloc(size, GFP_KERNEL);
if (dev->buf == NULL) @@ -186,8 +189,6 @@ static int chaoskey_probe(struct usb_int strcat(dev->name, udev->serial); }
- dev->interface = interface; - dev->in_ep = in_ep;
if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID)
From: Johan Hovold johan@kernel.org
commit 58ecf131e74620305175a7aa103f81350bb37570 upstream.
The driver was using its struct usb_interface pointer as an inverted disconnected flag, but was setting it to NULL before making sure all completion handlers had run. This could lead to a NULL-pointer dereference in a number of dev_dbg, dev_warn and dev_err statements in the completion handlers which relies on said pointer.
Fix this by unconditionally stopping all I/O and preventing resubmissions by poisoning the interrupt URBs at disconnect and using a dedicated disconnected flag.
This also makes sure that all I/O has completed by the time the disconnect callback returns.
Fixes: 2824bd250f0b ("[PATCH] USB: add ldusb driver") Cc: stable stable@vger.kernel.org # 2.6.13 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009153848.8664-4-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/ldusb.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
--- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -157,6 +157,7 @@ MODULE_PARM_DESC(min_interrupt_out_inter struct ld_usb { struct mutex mutex; /* locks this structure */ struct usb_interface *intf; /* save off the usb interface pointer */ + unsigned long disconnected:1;
int open_count; /* number of times this port has been opened */
@@ -196,12 +197,10 @@ static void ld_usb_abort_transfers(struc /* shutdown transfer */ if (dev->interrupt_in_running) { dev->interrupt_in_running = 0; - if (dev->intf) - usb_kill_urb(dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_in_urb); } if (dev->interrupt_out_busy) - if (dev->intf) - usb_kill_urb(dev->interrupt_out_urb); + usb_kill_urb(dev->interrupt_out_urb); }
/** @@ -209,8 +208,6 @@ static void ld_usb_abort_transfers(struc */ static void ld_usb_delete(struct ld_usb *dev) { - ld_usb_abort_transfers(dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -266,7 +263,7 @@ static void ld_usb_interrupt_in_callback
resubmit: /* resubmit if we're still running */ - if (dev->interrupt_in_running && !dev->buffer_overflow && dev->intf) { + if (dev->interrupt_in_running && !dev->buffer_overflow) { retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); if (retval) { dev_err(&dev->intf->dev, @@ -395,7 +392,7 @@ static int ld_usb_release(struct inode * retval = -ENODEV; goto unlock_exit; } - if (dev->intf == NULL) { + if (dev->disconnected) { /* the device was unplugged before the file was released */ mutex_unlock(&dev->mutex); /* unlock here as ld_usb_delete frees dev */ @@ -426,7 +423,7 @@ static unsigned int ld_usb_poll(struct f
dev = file->private_data;
- if (!dev->intf) + if (dev->disconnected) return POLLERR | POLLHUP;
poll_wait(file, &dev->read_wait, wait); @@ -465,7 +462,7 @@ static ssize_t ld_usb_read(struct file * }
/* verify that the device wasn't unplugged */ - if (dev->intf == NULL) { + if (dev->disconnected) { retval = -ENODEV; printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; @@ -545,7 +542,7 @@ static ssize_t ld_usb_write(struct file }
/* verify that the device wasn't unplugged */ - if (dev->intf == NULL) { + if (dev->disconnected) { retval = -ENODEV; printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; @@ -762,6 +759,9 @@ static void ld_usb_disconnect(struct usb /* give back our minor */ usb_deregister_dev(intf, &ld_usb_class);
+ usb_poison_urb(dev->interrupt_in_urb); + usb_poison_urb(dev->interrupt_out_urb); + mutex_lock(&dev->mutex);
/* if the device is not opened, then we clean up right now */ @@ -769,7 +769,7 @@ static void ld_usb_disconnect(struct usb mutex_unlock(&dev->mutex); ld_usb_delete(dev); } else { - dev->intf = NULL; + dev->disconnected = 1; /* wake up pollers */ wake_up_interruptible_all(&dev->read_wait); wake_up_interruptible_all(&dev->write_wait);
From: Randy Dunlap rdunlap@infradead.org
commit a553add0846f355a28ed4e81134012e4a1e280c2 upstream.
Call uart_unregister_driver() conditionally instead of unconditionally, only if it has been previously registered.
This uses driver.state, just as the sh-sci.c driver does.
Fixes this null pointer dereference in tty_unregister_driver(), since the 'driver' argument is null:
general protection fault: 0000 [#1] PREEMPT SMP KASAN PTI RIP: 0010:tty_unregister_driver+0x25/0x1d0
Fixes: 238b8721a554 ("[PATCH] serial uartlite driver") Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: stable stable@vger.kernel.org Cc: Peter Korsgaard jacmet@sunsite.dk Link: https://lore.kernel.org/r/9c8e6581-6fcc-a595-0897-4d90f5d710df@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/tty/serial/uartlite.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -746,7 +746,8 @@ err_uart: static void __exit ulite_exit(void) { platform_driver_unregister(&ulite_platform_driver); - uart_unregister_driver(&ulite_uart_driver); + if (ulite_uart_driver.state) + uart_unregister_driver(&ulite_uart_driver); }
module_init(ulite_init);
From: Johan Hovold johan@kernel.org
commit 7d7e21fafdbc7fcf0854b877bd0975b487ed2717 upstream.
Fix NULL-pointer dereferences on open() and write() which can be triggered by a malicious USB device.
The current URB allocation helper would fail to initialise the newly allocated URB if the device has unexpected endpoint descriptors, something which could lead NULL-pointer dereferences in a number of open() and write() paths when accessing the URB. For example:
BUG: kernel NULL pointer dereference, address: 0000000000000000 ... RIP: 0010:usb_clear_halt+0x11/0xc0 ... Call Trace: ? tty_port_open+0x4d/0xd0 keyspan_open+0x70/0x160 [keyspan] serial_port_activate+0x5b/0x80 [usbserial] tty_port_open+0x7b/0xd0 ? check_tty_count+0x43/0xa0 tty_open+0xf1/0x490
BUG: kernel NULL pointer dereference, address: 0000000000000000 ... RIP: 0010:keyspan_write+0x14e/0x1f3 [keyspan] ... Call Trace: serial_write+0x43/0xa0 [usbserial] n_tty_write+0x1af/0x4f0 ? do_wait_intr_irq+0x80/0x80 ? process_echoes+0x60/0x60 tty_write+0x13f/0x2f0
BUG: kernel NULL pointer dereference, address: 0000000000000000 ... RIP: 0010:keyspan_usa26_send_setup+0x298/0x305 [keyspan] ... Call Trace: keyspan_open+0x10f/0x160 [keyspan] serial_port_activate+0x5b/0x80 [usbserial] tty_port_open+0x7b/0xd0 ? check_tty_count+0x43/0xa0 tty_open+0xf1/0x490
Fixes: fdcba53e2d58 ("fix for bugzilla #7544 (keyspan USB-to-serial converter)") Cc: stable stable@vger.kernel.org # 2.6.21 Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/keyspan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1745,8 +1745,8 @@ static struct urb *keyspan_setup_urb(str
ep_desc = find_ep(serial, endpoint); if (!ep_desc) { - /* leak the urb, something's wrong and the callers don't care */ - return urb; + usb_free_urb(urb); + return NULL; } if (usb_endpoint_xfer_int(ep_desc)) { ep_type_name = "INT";
From: Beni Mahler beni.mahler@gmx.net
commit 357f16d9e0194cdbc36531ff88b453481560b76a upstream.
Both devices added here have a FTDI chip inside. The device from Echelon is called 'Network Interface' it is actually a LON network gateway.
ID 0403:8348 Future Technology Devices International, Ltd https://www.eltako.com/fileadmin/downloads/de/datenblatt/Datenblatt_PL-SW-PR...
ID 0920:7500 Network Interface https://www.echelon.com/products/u20-usb-network-interface
Signed-off-by: Beni Mahler beni.mahler@gmx.net Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio_ids.h | 9 +++++++++ 2 files changed, 12 insertions(+)
--- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1025,6 +1025,9 @@ static const struct usb_device_id id_tab /* EZPrototypes devices */ { USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) }, { USB_DEVICE_INTERFACE_NUMBER(UNJO_VID, UNJO_ISODEBUG_V1_PID, 1) }, + /* Sienna devices */ + { USB_DEVICE(FTDI_VID, FTDI_SIENNA_PID) }, + { USB_DEVICE(ECHELON_VID, ECHELON_U20_PID) }, { } /* Terminating entry */ };
--- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -39,6 +39,9 @@
#define FTDI_LUMEL_PD12_PID 0x6002
+/* Sienna Serial Interface by Secyourit GmbH */ +#define FTDI_SIENNA_PID 0x8348 + /* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ #define CYBER_CORTEX_AV_PID 0x8698
@@ -689,6 +692,12 @@ #define BANDB_ZZ_PROG1_USB_PID 0xBA02
/* + * Echelon USB Serial Interface + */ +#define ECHELON_VID 0x0920 +#define ECHELON_U20_PID 0x7500 + +/* * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI */ #define INTREPID_VID 0x093C
From: Daniele Palmas dnlplm@gmail.com
commit 5eb3f4b87a0e7e949c976f32f296176a06d1a93b upstream.
This patch adds the following Telit FN980 compositions:
0x1050: tty, adb, rmnet, tty, tty, tty, tty 0x1051: tty, adb, mbim, tty, tty, tty, tty 0x1052: rndis, tty, adb, tty, tty, tty, tty 0x1053: tty, adb, ecm, tty, tty, tty, tty
Signed-off-by: Daniele Palmas dnlplm@gmail.com Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/option.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1157,6 +1157,14 @@ static const struct usb_device_id option .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1050, 0xff), /* Telit FN980 (rmnet) */ + .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1051, 0xff), /* Telit FN980 (MBIM) */ + .driver_info = NCTRL(0) | RSVD(1) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1052, 0xff), /* Telit FN980 (RNDIS) */ + .driver_info = NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1053, 0xff), /* Telit FN980 (ECM) */ + .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
From: Reinhard Speyerer rspmn@arcor.de
commit dfbac2f4da6a0c4a8f6b4d715a4077a7b8df53ad upstream.
Add support for the serial ports of Cinterion CLS8 devices.
T: Bus=01 Lev=03 Prnt=05 Port=01 Cnt=02 Dev#= 25 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1e2d ProdID=00b0 Rev= 3.18 S: Manufacturer=GEMALTO S: Product=USB Modem C:* #Ifs= 5 Cfg#= 1 Atr=80 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Signed-off-by: Reinhard Speyerer rspmn@arcor.de Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -422,6 +422,7 @@ static void option_instat_callback(struc #define CINTERION_PRODUCT_PH8_AUDIO 0x0083 #define CINTERION_PRODUCT_AHXX_2RMNET 0x0084 #define CINTERION_PRODUCT_AHXX_AUDIO 0x0085 +#define CINTERION_PRODUCT_CLS8 0x00b0
/* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c @@ -1858,6 +1859,8 @@ static const struct usb_device_id option .driver_info = RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_2RMNET, 0xff) }, { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_AUDIO, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_CLS8, 0xff), + .driver_info = RSVD(0) | RSVD(4) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
From: Johan Hovold johan@kernel.org
commit d51bdb93ca7e71d7fb30a572c7b47ed0194bf3fe upstream.
Since commit c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") USB drivers must always balance their runtime PM gets and puts, including when the driver has already been unbound from the interface.
Leaving the interface with a positive PM usage counter would prevent a later bound driver from suspending the device.
Fixes: c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191001084908.2003-4-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/usb-serial.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
--- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -314,10 +314,7 @@ static void serial_cleanup(struct tty_st serial = port->serial; owner = serial->type->driver.owner;
- mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) - usb_autopm_put_interface(serial->interface); - mutex_unlock(&serial->disc_mutex); + usb_autopm_put_interface(serial->interface);
usb_serial_put(serial); module_put(owner);
From: Johan Hovold johan@kernel.org
commit eb7f5a490c5edfe8126f64bc58b9ba2edef0a425 upstream.
Make sure to stop all I/O on disconnect by adding a disconnected flag which is used to prevent new I/O from being started and by stopping all ongoing I/O before returning.
This also fixes a potential use-after-free on driver unbind in case the driver data is freed before the completion handler has run.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable stable@vger.kernel.org # 7bbe990c989e Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20190926091228.24634-7-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/usblcd.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
--- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -17,6 +17,7 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/mutex.h> +#include <linux/rwsem.h> #include <linux/uaccess.h> #include <linux/usb.h>
@@ -56,6 +57,8 @@ struct usb_lcd { using up all RAM */ struct usb_anchor submitted; /* URBs to wait for before suspend */ + struct rw_semaphore io_rwsem; + unsigned long disconnected:1; }; #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
@@ -141,6 +144,13 @@ static ssize_t lcd_read(struct file *fil
dev = file->private_data;
+ down_read(&dev->io_rwsem); + + if (dev->disconnected) { + retval = -ENODEV; + goto out_up_io; + } + /* do a blocking bulk read to get data from the device */ retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, @@ -157,6 +167,9 @@ static ssize_t lcd_read(struct file *fil retval = bytes_read; }
+out_up_io: + up_read(&dev->io_rwsem); + return retval; }
@@ -236,11 +249,18 @@ static ssize_t lcd_write(struct file *fi if (r < 0) return -EINTR;
+ down_read(&dev->io_rwsem); + + if (dev->disconnected) { + retval = -ENODEV; + goto err_up_io; + } + /* create a urb, and a buffer for it, and copy the data to the urb */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; - goto err_no_buf; + goto err_up_io; }
buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL, @@ -277,6 +297,7 @@ static ssize_t lcd_write(struct file *fi the USB core will eventually free it entirely */ usb_free_urb(urb);
+ up_read(&dev->io_rwsem); exit: return count; error_unanchor: @@ -284,7 +305,8 @@ error_unanchor: error: usb_free_coherent(dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); -err_no_buf: +err_up_io: + up_read(&dev->io_rwsem); up(&dev->limit_sem); return retval; } @@ -324,6 +346,7 @@ static int lcd_probe(struct usb_interfac
kref_init(&dev->kref); sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); + init_rwsem(&dev->io_rwsem); init_usb_anchor(&dev->submitted);
dev->udev = usb_get_dev(interface_to_usbdev(interface)); @@ -421,6 +444,12 @@ static void lcd_disconnect(struct usb_in /* give back our minor */ usb_deregister_dev(interface, &lcd_class);
+ down_write(&dev->io_rwsem); + dev->disconnected = 1; + up_write(&dev->io_rwsem); + + usb_kill_anchored_urbs(&dev->submitted); + /* decrement our usage count */ kref_put(&dev->kref, lcd_delete);
From: Johan Hovold johan@kernel.org
commit 177238c3d47d54b2ed8f0da7a4290db492f4a057 upstream.
Add missing bulk-in endpoint sanity check to prevent uninitialised stack data from being reported to the system log and used as endpoint addresses.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable stable@vger.kernel.org Reported-by: syzbot+5630ca7c3b2be5c9da5e@syzkaller.appspotmail.com Signed-off-by: Johan Hovold johan@kernel.org Acked-by: Oliver Neukum oneukum@suse.com Link: https://lore.kernel.org/r/20191003070931.17009-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/image/microtek.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -720,6 +720,10 @@ static int mts_usb_probe(struct usb_inte
}
+ if (ep_in_current != &ep_in_set[2]) { + MTS_WARNING("couldn't find two input bulk endpoints. Bailing out.\n"); + return -ENODEV; + }
if ( ep_out == -1 ) { MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
From: Jacky.Cao@sony.com Jacky.Cao@sony.com
commit 2636d49b64671d3d90ecc4daf971b58df3956519 upstream.
The power budget for SuperSpeed mode should be 900 mA according to USB specification, so set the power budget to 900mA for dummy_start_ss which is only used for SuperSpeed mode.
If the max power consumption of SuperSpeed device is larger than 500 mA, insufficient available bus power error happens in usb_choose_configuration function when the device connects to dummy hcd.
Signed-off-by: Jacky Cao Jacky.Cao@sony.com Acked-by: Alan Stern stern@rowland.harvard.edu Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/16EA1F625E922C43B00B9D82250220500871CDE5@APYOKXMS1... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/gadget/udc/dummy_hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -50,6 +50,7 @@ #define DRIVER_VERSION "02 May 2005"
#define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */ +#define POWER_BUDGET_3 900 /* in mA */
static const char driver_name[] = "dummy_hcd"; static const char driver_desc[] = "USB Host+Gadget Emulator"; @@ -2439,7 +2440,7 @@ static int dummy_start_ss(struct dummy_h dum_hcd->rh_state = DUMMY_RH_RUNNING; dum_hcd->stream_en_ep = 0; INIT_LIST_HEAD(&dum_hcd->urbp_list); - dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET; + dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET_3; dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING; dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1; #ifdef CONFIG_USB_OTG
From: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com
commit 1aae1394294cb71c6aa0bc904a94a7f2f1e75936 upstream.
The commit 97664a207bc2 ("usb: renesas_usbhs: shrink spin lock area") had added a usbhsg_pipe_disable() calling into __usbhsg_ep_set_halt_wedge() accidentally. But, this driver should not call the usbhsg_pipe_disable() because the function discards all queues. So, this patch removes it.
Fixes: 97664a207bc2 ("usb: renesas_usbhs: shrink spin lock area") Cc: stable@vger.kernel.org # v3.1+ Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Link: https://lore.kernel.org/r/1569924633-322-2-git-send-email-yoshihiro.shimoda.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/renesas_usbhs/mod_gadget.c | 2 -- 1 file changed, 2 deletions(-)
--- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -730,8 +730,6 @@ static int __usbhsg_ep_set_halt_wedge(st struct device *dev = usbhsg_gpriv_to_dev(gpriv); unsigned long flags;
- usbhsg_pipe_disable(uep); - dev_dbg(dev, "set halt %d (pipe %d)\n", halt, usbhs_pipe_number(pipe));
From: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com
commit 4d599cd3a097a85a5c68a2c82b9a48cddf9953ec upstream.
According to usb_ep_set_halt()'s description, __usbhsg_ep_set_halt_wedge() should return -EAGAIN if the IN endpoint has any queue or data. Otherwise, this driver is possible to cause just STALL without sending a short packet data on g_mass_storage driver, and then a few resetting a device happens on a host side during a usb enumaration.
Fixes: 2f98382dcdfe ("usb: renesas_usbhs: Add Renesas USBHS Gadget") Cc: stable@vger.kernel.org # v3.0+ Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Link: https://lore.kernel.org/r/1569924633-322-3-git-send-email-yoshihiro.shimoda.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/renesas_usbhs/common.h | 1 + drivers/usb/renesas_usbhs/fifo.c | 2 +- drivers/usb/renesas_usbhs/fifo.h | 1 + drivers/usb/renesas_usbhs/mod_gadget.c | 16 +++++++++++++++- drivers/usb/renesas_usbhs/pipe.c | 15 +++++++++++++++ drivers/usb/renesas_usbhs/pipe.h | 1 + 6 files changed, 34 insertions(+), 2 deletions(-)
--- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -213,6 +213,7 @@ struct usbhs_priv; /* DCPCTR */ #define BSTS (1 << 15) /* Buffer Status */ #define SUREQ (1 << 14) /* Sending SETUP Token */ +#define INBUFM (1 << 14) /* (PIPEnCTR) Transfer Buffer Monitor */ #define CSSTS (1 << 12) /* CSSTS Status */ #define ACLRM (1 << 9) /* Buffer Auto-Clear Mode */ #define SQCLR (1 << 8) /* Toggle Bit Clear */ --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -98,7 +98,7 @@ static void __usbhsf_pkt_del(struct usbh list_del_init(&pkt->node); }
-static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) +struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) { return list_first_entry_or_null(&pipe->list, struct usbhs_pkt, node); } --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -106,5 +106,6 @@ void usbhs_pkt_push(struct usbhs_pipe *p void *buf, int len, int zero, int sequence); struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); void usbhs_pkt_start(struct usbhs_pipe *pipe); +struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe);
#endif /* RENESAS_USB_FIFO_H */ --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -729,6 +729,7 @@ static int __usbhsg_ep_set_halt_wedge(st struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); struct device *dev = usbhsg_gpriv_to_dev(gpriv); unsigned long flags; + int ret = 0;
dev_dbg(dev, "set halt %d (pipe %d)\n", halt, usbhs_pipe_number(pipe)); @@ -736,6 +737,18 @@ static int __usbhsg_ep_set_halt_wedge(st /******************** spin lock ********************/ usbhs_lock(priv, flags);
+ /* + * According to usb_ep_set_halt()'s description, this function should + * return -EAGAIN if the IN endpoint has any queue or data. Note + * that the usbhs_pipe_is_dir_in() returns false if the pipe is an + * IN endpoint in the gadget mode. + */ + if (!usbhs_pipe_is_dir_in(pipe) && (__usbhsf_pkt_get(pipe) || + usbhs_pipe_contains_transmittable_data(pipe))) { + ret = -EAGAIN; + goto out; + } + if (halt) usbhs_pipe_stall(pipe); else @@ -746,10 +759,11 @@ static int __usbhsg_ep_set_halt_wedge(st else usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE);
+out: usbhs_unlock(priv, flags); /******************** spin unlock ******************/
- return 0; + return ret; }
static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -286,6 +286,21 @@ int usbhs_pipe_is_accessible(struct usbh return -EBUSY; }
+bool usbhs_pipe_contains_transmittable_data(struct usbhs_pipe *pipe) +{ + u16 val; + + /* Do not support for DCP pipe */ + if (usbhs_pipe_is_dcp(pipe)) + return false; + + val = usbhsp_pipectrl_get(pipe); + if (val & INBUFM) + return true; + + return false; +} + /* * PID ctrl */ --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -90,6 +90,7 @@ void usbhs_pipe_init(struct usbhs_priv * int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); void usbhs_pipe_clear(struct usbhs_pipe *pipe); int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe); +bool usbhs_pipe_contains_transmittable_data(struct usbhs_pipe *pipe); void usbhs_pipe_enable(struct usbhs_pipe *pipe); void usbhs_pipe_disable(struct usbhs_pipe *pipe); void usbhs_pipe_stall(struct usbhs_pipe *pipe);
From: Johan Hovold johan@kernel.org
commit 1d427be4a39defadda6dd8f4659bc17f7591740f upstream.
Make sure to check for short transfers when retrieving the version information at probe to avoid leaking uninitialised slab data when logging it.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20190919083039.30898-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/legousbtower.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -894,8 +894,10 @@ static int tower_probe (struct usb_inter get_version_reply, sizeof(*get_version_reply), 1000); - if (result < 0) { - dev_err(idev, "LEGO USB Tower get version control request failed\n"); + if (result < sizeof(*get_version_reply)) { + if (result >= 0) + result = -EIO; + dev_err(idev, "get version request failed: %d\n", result); retval = result; goto error; }
From: Johan Hovold johan@kernel.org
commit 33a7813219f208f4952ece60ee255fd983272dec upstream.
Fix a potential deadlock if disconnect races with open.
Since commit d4ead16f50f9 ("USB: prevent char device open/deregister race") core holds an rw-semaphore while open is called and when releasing the minor number during deregistration. This can lead to an ABBA deadlock if a driver takes a lock in open which it also holds during deregistration.
This effectively reverts commit 78663ecc344b ("USB: disconnect open race in legousbtower") which needlessly introduced this issue after a generic fix for this race had been added to core by commit d4ead16f50f9 ("USB: prevent char device open/deregister race").
Fixes: 78663ecc344b ("USB: disconnect open race in legousbtower") Cc: stable stable@vger.kernel.org # 2.6.24 Reported-by: syzbot+f9549f5ee8a5416f0b95@syzkaller.appspotmail.com Tested-by: syzbot+f9549f5ee8a5416f0b95@syzkaller.appspotmail.com Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20190919083039.30898-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/legousbtower.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-)
--- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -183,7 +183,6 @@ static const struct usb_device_id tower_ };
MODULE_DEVICE_TABLE (usb, tower_table); -static DEFINE_MUTEX(open_disc_mutex);
#define LEGO_USB_TOWER_MINOR_BASE 160
@@ -336,18 +335,14 @@ static int tower_open (struct inode *ino goto exit; }
- mutex_lock(&open_disc_mutex); dev = usb_get_intfdata(interface); - if (!dev) { - mutex_unlock(&open_disc_mutex); retval = -ENODEV; goto exit; }
/* lock this device */ if (mutex_lock_interruptible(&dev->lock)) { - mutex_unlock(&open_disc_mutex); retval = -ERESTARTSYS; goto exit; } @@ -355,12 +350,10 @@ static int tower_open (struct inode *ino
/* allow opening only once */ if (dev->open_count) { - mutex_unlock(&open_disc_mutex); retval = -EBUSY; goto unlock_exit; } dev->open_count = 1; - mutex_unlock(&open_disc_mutex);
/* reset the tower */ result = usb_control_msg (dev->udev, @@ -427,10 +420,9 @@ static int tower_release (struct inode *
if (dev == NULL) { retval = -ENODEV; - goto exit_nolock; + goto exit; }
- mutex_lock(&open_disc_mutex); if (mutex_lock_interruptible(&dev->lock)) { retval = -ERESTARTSYS; goto exit; @@ -460,10 +452,7 @@ static int tower_release (struct inode *
unlock_exit: mutex_unlock(&dev->lock); - exit: - mutex_unlock(&open_disc_mutex); -exit_nolock: return retval; }
@@ -915,7 +904,6 @@ static int tower_probe (struct usb_inter if (retval) { /* something prevented us from registering this driver */ dev_err(idev, "Not able to get a minor for this device.\n"); - usb_set_intfdata (interface, NULL); goto error; } dev->minor = interface->minor; @@ -947,16 +935,13 @@ static void tower_disconnect (struct usb int minor;
dev = usb_get_intfdata (interface); - mutex_lock(&open_disc_mutex); - usb_set_intfdata (interface, NULL);
minor = dev->minor;
- /* give back our minor */ + /* give back our minor and prevent further open() */ usb_deregister_dev (interface, &tower_class);
mutex_lock(&dev->lock); - mutex_unlock(&open_disc_mutex);
/* if the device is not opened, then we clean up right now */ if (!dev->open_count) {
From: Johan Hovold johan@kernel.org
commit cd81e6fa8e033e7bcd59415b4a65672b4780030b upstream.
The driver is using its struct usb_device pointer as an inverted disconnected flag, but was setting it to NULL before making sure all completion handlers had run. This could lead to a NULL-pointer dereference in a number of dev_dbg and dev_err statements in the completion handlers which relies on said pointer.
Fix this by unconditionally stopping all I/O and preventing resubmissions by poisoning the interrupt URBs at disconnect and using a dedicated disconnected flag.
This also makes sure that all I/O has completed by the time the disconnect callback returns.
Fixes: 9d974b2a06e3 ("USB: legousbtower.c: remove err() usage") Fixes: fef526cae700 ("USB: legousbtower: remove custom debug macro") Fixes: 4dae99638097 ("USB: legotower: remove custom debug macro and module parameter") Cc: stable stable@vger.kernel.org # 3.5 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20190919083039.30898-4-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/legousbtower.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-)
--- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -194,6 +194,7 @@ struct lego_usb_tower { unsigned char minor; /* the starting minor number for this device */
int open_count; /* number of times this port has been opened */ + unsigned long disconnected:1;
char* read_buffer; size_t read_buffer_length; /* this much came in */ @@ -293,8 +294,6 @@ static inline void lego_usb_tower_debug_ */ static inline void tower_delete (struct lego_usb_tower *dev) { - tower_abort_transfers (dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -434,7 +433,8 @@ static int tower_release (struct inode * retval = -ENODEV; goto unlock_exit; } - if (dev->udev == NULL) { + + if (dev->disconnected) { /* the device was unplugged before the file was released */
/* unlock here as tower_delete frees dev */ @@ -470,10 +470,9 @@ static void tower_abort_transfers (struc if (dev->interrupt_in_running) { dev->interrupt_in_running = 0; mb(); - if (dev->udev) - usb_kill_urb (dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_in_urb); } - if (dev->interrupt_out_busy && dev->udev) + if (dev->interrupt_out_busy) usb_kill_urb(dev->interrupt_out_urb); }
@@ -509,7 +508,7 @@ static unsigned int tower_poll (struct f
dev = file->private_data;
- if (!dev->udev) + if (dev->disconnected) return POLLERR | POLLHUP;
poll_wait(file, &dev->read_wait, wait); @@ -556,7 +555,7 @@ static ssize_t tower_read (struct file * }
/* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; @@ -642,7 +641,7 @@ static ssize_t tower_write (struct file }
/* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; @@ -751,7 +750,7 @@ static void tower_interrupt_in_callback
resubmit: /* resubmit if we're still running */ - if (dev->interrupt_in_running && dev->udev) { + if (dev->interrupt_in_running) { retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC); if (retval) dev_err(&dev->udev->dev, @@ -816,6 +815,7 @@ static int tower_probe (struct usb_inter
dev->udev = udev; dev->open_count = 0; + dev->disconnected = 0;
dev->read_buffer = NULL; dev->read_buffer_length = 0; @@ -941,6 +941,10 @@ static void tower_disconnect (struct usb /* give back our minor and prevent further open() */ usb_deregister_dev (interface, &tower_class);
+ /* stop I/O */ + usb_poison_urb(dev->interrupt_in_urb); + usb_poison_urb(dev->interrupt_out_urb); + mutex_lock(&dev->lock);
/* if the device is not opened, then we clean up right now */ @@ -948,7 +952,7 @@ static void tower_disconnect (struct usb mutex_unlock(&dev->lock); tower_delete (dev); } else { - dev->udev = NULL; + dev->disconnected = 1; /* wake up pollers */ wake_up_interruptible_all(&dev->read_wait); wake_up_interruptible_all(&dev->write_wait);
From: Johan Hovold johan@kernel.org
commit 0b074f6986751361ff442bc1127c1648567aa8d6 upstream.
The driver would return with a nonzero open count in case the reset control request failed. This would prevent any further attempts to open the char dev until the device was disconnected.
Fix this by incrementing the open count only on successful open.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Johan Hovold johan@kernel.org Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20190919083039.30898-5-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/legousbtower.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -352,7 +352,6 @@ static int tower_open (struct inode *ino retval = -EBUSY; goto unlock_exit; } - dev->open_count = 1;
/* reset the tower */ result = usb_control_msg (dev->udev, @@ -392,13 +391,14 @@ static int tower_open (struct inode *ino dev_err(&dev->udev->dev, "Couldn't submit interrupt_in_urb %d\n", retval); dev->interrupt_in_running = 0; - dev->open_count = 0; goto unlock_exit; }
/* save device in the file's private structure */ file->private_data = dev;
+ dev->open_count = 1; + unlock_exit: mutex_unlock(&dev->lock);
From: Johan Hovold johan@kernel.org
commit 726b55d0e22ca72c69c947af87785c830289ddbc upstream.
The driver was accessing its struct usb_device in its release() callback without holding a reference. This would lead to a use-after-free whenever the device was disconnected while the character device was still open.
Fixes: fef526cae700 ("USB: legousbtower: remove custom debug macro") Cc: stable stable@vger.kernel.org # 3.12 Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191009153848.8664-5-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/legousbtower.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -300,6 +300,7 @@ static inline void tower_delete (struct kfree (dev->read_buffer); kfree (dev->interrupt_in_buffer); kfree (dev->interrupt_out_buffer); + usb_put_dev(dev->udev); kfree (dev); }
@@ -813,7 +814,7 @@ static int tower_probe (struct usb_inter
mutex_init(&dev->lock);
- dev->udev = udev; + dev->udev = usb_get_dev(udev); dev->open_count = 0; dev->disconnected = 0;
From: Navid Emamdoost navid.emamdoost@gmail.com
commit 80b15db5e1e9c3300de299b2d43d1aafb593e6ac upstream.
In vt6655_probe, if vnt_init() fails the cleanup code needs to be called like other error handling cases. The call to device_free_info() is added.
Fixes: 67013f2c0e58 ("staging: vt6655: mac80211 conversion add main mac80211 functions") Signed-off-by: Navid Emamdoost navid.emamdoost@gmail.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20191004200319.22394-1-navid.emamdoost@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/staging/vt6655/device_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1668,8 +1668,10 @@ vt6655_probe(struct pci_dev *pcid, const
priv->hw->max_signal = 100;
- if (vnt_init(priv)) + if (vnt_init(priv)) { + device_free_info(priv); return -ENODEV; + }
device_print_info(priv); pci_set_drvdata(pcid, priv);
From: Marco Felsch m.felsch@pengutronix.de
commit c62dd44901cfff12acc5792bf3d2dec20bcaf392 upstream.
Since commit 0f7ddcc1bff1 ("iio:adc:ad799x: Write default config on probe and reset alert status on probe") the error path is wrong since it leaves the vref regulator on. Fix this by disabling both regulators.
Fixes: 0f7ddcc1bff1 ("iio:adc:ad799x: Write default config on probe and reset alert status on probe") Signed-off-by: Marco Felsch m.felsch@pengutronix.de Reviewed-by: Alexandru Ardelean alexandru.ardelean@analog.com Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/iio/adc/ad799x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -817,10 +817,10 @@ static int ad799x_probe(struct i2c_clien
ret = ad799x_write_config(st, st->chip_config->default_config); if (ret < 0) - goto error_disable_reg; + goto error_disable_vref; ret = ad799x_read_config(st); if (ret < 0) - goto error_disable_reg; + goto error_disable_vref; st->config = ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
From: Hans de Goede hdegoede@redhat.com
commit 972917419a0ba25afbf69d5d8c9fa644d676f887 upstream.
Since commit 9bcf15f75cac ("iio: adc: axp288: Fix TS-pin handling") we preserve the bias current set by the firmware at boot. This fixes issues we were seeing on various models, but it seems our old hardcoded 80ųA bias current was working around a firmware bug on at least one model laptop.
In order to both have our cake and eat it, this commit adds a dmi based list of models where we need to override the firmware set bias current and adds the one model we now know needs this to it: The Lenovo Ideapad 100S (11 inch version).
Fixes: 9bcf15f75cac ("iio: adc: axp288: Fix TS-pin handling") BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=203829 Signed-off-by: Hans de Goede hdegoede@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/iio/adc/axp288_adc.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
--- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -16,6 +16,7 @@ * */
+#include <linux/dmi.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> @@ -34,6 +35,11 @@ #define AXP288_ADC_EN_MASK 0xF0 #define AXP288_ADC_TS_ENABLE 0x01
+#define AXP288_ADC_TS_BIAS_MASK GENMASK(5, 4) +#define AXP288_ADC_TS_BIAS_20UA (0 << 4) +#define AXP288_ADC_TS_BIAS_40UA (1 << 4) +#define AXP288_ADC_TS_BIAS_60UA (2 << 4) +#define AXP288_ADC_TS_BIAS_80UA (3 << 4) #define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0) #define AXP288_ADC_TS_CURRENT_OFF (0 << 0) #define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0) @@ -194,10 +200,36 @@ static int axp288_adc_read_raw(struct ii return ret; }
+/* + * We rely on the machine's firmware to correctly setup the TS pin bias current + * at boot. This lists systems with broken fw where we need to set it ourselves. + */ +static const struct dmi_system_id axp288_adc_ts_bias_override[] = { + { + /* Lenovo Ideapad 100S (11 inch) */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 100S-11IBY"), + }, + .driver_data = (void *)(uintptr_t)AXP288_ADC_TS_BIAS_80UA, + }, + {} +}; + static int axp288_adc_initialize(struct axp288_adc_info *info) { + const struct dmi_system_id *bias_override; int ret, adc_enable_val;
+ bias_override = dmi_first_match(axp288_adc_ts_bias_override); + if (bias_override) { + ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_BIAS_MASK, + (uintptr_t)bias_override->driver_data); + if (ret) + return ret; + } + /* * Determine if the TS pin is enabled and set the TS current-source * accordingly.
From: David Frey dpfrey@gmail.com
commit 82f3015635249a8c8c45bac303fd84905066f04f upstream.
When an end-of-conversion interrupt is received after performing a single-shot reading of the light sensor, the driver was waking up the result ready queue before checking opt->ok_to_ignore_lock to determine if it should unlock the mutex. The problem occurred in the case where the other thread woke up and changed the value of opt->ok_to_ignore_lock to false prior to the interrupt thread performing its read of the variable. In this case, the mutex would be unlocked twice.
Signed-off-by: David Frey dpfrey@gmail.com Reviewed-by: Andreas Dannenberg dannenberg@ti.com Fixes: 94a9b7b1809f ("iio: light: add support for TI's opt3001 light sensor") Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/iio/light/opt3001.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -695,6 +695,7 @@ static irqreturn_t opt3001_irq(int irq, struct iio_dev *iio = _iio; struct opt3001 *opt = iio_priv(iio); int ret; + bool wake_result_ready_queue = false;
if (!opt->ok_to_ignore_lock) mutex_lock(&opt->lock); @@ -729,13 +730,16 @@ static irqreturn_t opt3001_irq(int irq, } opt->result = ret; opt->result_ready = true; - wake_up(&opt->result_ready_queue); + wake_result_ready_queue = true; }
out: if (!opt->ok_to_ignore_lock) mutex_unlock(&opt->lock);
+ if (wake_result_ready_queue) + wake_up(&opt->result_ready_queue); + return IRQ_HANDLED; }
From: Ard Biesheuvel ard.biesheuvel@linaro.org
commit c05f8f92b701576b615f30aac31fabdc0648649b upstream.
The kernel command line option efivar_ssdt= allows the name to be specified of an EFI variable containing an ACPI SSDT table that should be loaded into memory by the OS, and treated as if it was provided by the firmware.
Currently, that code will always iterate over the EFI variables and compare each name with the provided name, even if the command line option wasn't set to begin with.
So bail early when no variable name was provided. This works around a boot regression on the 2012 Mac Pro, as reported by Scott.
Tested-by: Scott Talbert swt@techie.net Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org Cc: stable@vger.kernel.org # v4.9+ Cc: Ben Dooks ben.dooks@codethink.co.uk Cc: Dave Young dyoung@redhat.com Cc: Jarkko Sakkinen jarkko.sakkinen@linux.intel.com Cc: Jerry Snitselaar jsnitsel@redhat.com Cc: Linus Torvalds torvalds@linux-foundation.org Cc: Lukas Wunner lukas@wunner.de Cc: Lyude Paul lyude@redhat.com Cc: Matthew Garrett mjg59@google.com Cc: Octavian Purdila octavian.purdila@intel.com Cc: Peter Jones pjones@redhat.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: linux-efi@vger.kernel.org Cc: linux-integrity@vger.kernel.org Fixes: 475fb4e8b2f4 ("efi / ACPI: load SSTDs from EFI variables") Link: https://lkml.kernel.org/r/20191002165904.8819-3-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar mingo@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/firmware/efi/efi.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -266,6 +266,9 @@ static __init int efivar_ssdt_load(void) void *data; int ret;
+ if (!efivar_ssdt[0]) + return 0; + ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries);
list_for_each_entry_safe(entry, aux, &entries, list) {
From: Ian Rogers irogers@google.com
commit 7d4c85b7035eb2f9ab217ce649dcd1bfaf0cacd3 upstream.
The 'test_dir' variable is assigned to the 'release' array which is out-of-scope 3 lines later.
Extend the scope of the 'release' array so that an out-of-scope array isn't accessed.
Bug detected by clang's address sanitizer.
Fixes: 07bc5c699a3d ("perf tools: Make fetch_kernel_version() publicly available") Cc: stable@vger.kernel.org # v4.4+ Signed-off-by: Ian Rogers irogers@google.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Andi Kleen ak@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Stephane Eranian eranian@google.com Cc: Wang Nan wangnan0@huawei.com Link: http://lore.kernel.org/lkml/20190926220018.25402-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- tools/perf/util/llvm-utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c @@ -225,14 +225,14 @@ static int detect_kbuild_dir(char **kbui const char *prefix_dir = ""; const char *suffix_dir = "";
+ /* _UTSNAME_LENGTH is 65 */ + char release[128]; + char *autoconf_path;
int err;
if (!test_dir) { - /* _UTSNAME_LENGTH is 65 */ - char release[128]; - err = fetch_kernel_version(NULL, release, sizeof(release)); if (err)
From: Steve MacLean Steve.MacLean@microsoft.com
commit b59711e9b0d22fd47abfa00602fd8c365cdd3ab7 upstream.
During perf inject --jit, JIT_CODE_MOVE records were injecting MMAP records with an incorrect filename. Specifically it was missing the ".so" suffix.
Further the JIT_CODE_LOAD record were silently truncating the jr->load.code_index field to 32 bits before generating the filename.
Make both records emit the same filename based on the full 64 bit code_index field.
Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Cc: stable@vger.kernel.org # v4.6+ Signed-off-by: Steve MacLean Steve.MacLean@Microsoft.com Acked-by: Jiri Olsa jolsa@kernel.org Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Andi Kleen ak@linux.intel.com Cc: Brian Robbins brianrob@microsoft.com Cc: Davidlohr Bueso dave@stgolabs.net Cc: Eric Saint-Etienne eric.saint.etienne@oracle.com Cc: John Keeping john@metanate.com Cc: John Salem josalem@microsoft.com Cc: Leo Yan leo.yan@linaro.org Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Song Liu songliubraving@fb.com Cc: Stephane Eranian eranian@google.com Cc: Tom McDonald thomas.mcdonald@microsoft.com Link: http://lore.kernel.org/lkml/BN8PR21MB1362FF8F127B31DBF4121528F7800@BN8PR21MB... Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- tools/perf/util/jitdump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -394,7 +394,7 @@ static int jit_repipe_code_load(struct j size_t size; u16 idr_size; const char *sym; - uint32_t count; + uint64_t count; int ret, csize, usize; pid_t pid, tid; struct { @@ -417,7 +417,7 @@ static int jit_repipe_code_load(struct j return -1;
filename = event->mmap2.filename; - size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%u.so", + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so", jd->dir, pid, count); @@ -530,7 +530,7 @@ static int jit_repipe_code_move(struct j return -1;
filename = event->mmap2.filename; - size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%"PRIu64, + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so", jd->dir, pid, jr->move.code_index);
From: Pavel Shilovsky piastryyy@gmail.com
commit 30573a82fb179420b8aac30a3a3595aa96a93156 upstream.
Currently if the client identifies problems when processing metadata returned in CREATE response, the open handle is being leaked. This causes multiple problems like a file missing a lease break by that client which causes high latencies to other clients accessing the file. Another side-effect of this is that the file can't be deleted.
Fix this by closing the file after the client hits an error after the file was opened and the open descriptor wasn't returned to the user space. Also convert -ESTALE to -EOPENSTALE to allow the VFS to revalidate a dentry and retry the open.
Cc: stable@vger.kernel.org Signed-off-by: Pavel Shilovsky pshilov@microsoft.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/file.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -252,6 +252,12 @@ cifs_nt_open(char *full_path, struct ino rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, xid, fid);
+ if (rc) { + server->ops->close(xid, tcon, fid); + if (rc == -ESTALE) + rc = -EOPENSTALE; + } + out: kfree(buf); return rc;
From: Pavel Shilovsky piastryyy@gmail.com
commit c82e5ac7fe3570a269c0929bf7899f62048e7dbc upstream.
Currently the client indicates that a dentry is stale when inode numbers or type types between a local inode and a remote file don't match. If this is the case attributes is not being copied from remote to local, so, it is already known that the local copy has stale metadata. That's why the inode needs to be marked for revalidation in order to tell the VFS to lookup the dentry again before openning a file. This prevents unexpected stale errors to be returned to the user space when openning a file.
Cc: stable@vger.kernel.org Signed-off-by: Pavel Shilovsky pshilov@microsoft.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/inode.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -410,6 +410,7 @@ int cifs_get_inode_info_unix(struct inod /* if uniqueid is different, return error */ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM && CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) { + CIFS_I(*pinode)->time = 0; /* force reval */ rc = -ESTALE; goto cgiiu_exit; } @@ -417,6 +418,7 @@ int cifs_get_inode_info_unix(struct inod /* if filetype is different, return error */ if (unlikely(((*pinode)->i_mode & S_IFMT) != (fattr.cf_mode & S_IFMT))) { + CIFS_I(*pinode)->time = 0; /* force reval */ rc = -ESTALE; goto cgiiu_exit; } @@ -925,6 +927,7 @@ cifs_get_inode_info(struct inode **inode /* if uniqueid is different, return error */ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM && CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) { + CIFS_I(*inode)->time = 0; /* force reval */ rc = -ESTALE; goto cgii_exit; } @@ -932,6 +935,7 @@ cifs_get_inode_info(struct inode **inode /* if filetype is different, return error */ if (unlikely(((*inode)->i_mode & S_IFMT) != (fattr.cf_mode & S_IFMT))) { + CIFS_I(*inode)->time = 0; /* force reval */ rc = -ESTALE; goto cgii_exit; }
From: Pavel Shilovsky piastryyy@gmail.com
commit 0b3d0ef9840f7be202393ca9116b857f6f793715 upstream.
Mark inode for force revalidation if LOOKUP_REVAL flag is set. This tells the client to actually send a QueryInfo request to the server to obtain the latest metadata in case a directory or a file were changed remotely. Only do that if the client doesn't have a lease for the file to avoid unneeded round trips to the server.
Cc: stable@vger.kernel.org Signed-off-by: Pavel Shilovsky pshilov@microsoft.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/dir.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -841,10 +841,16 @@ lookup_out: static int cifs_d_revalidate(struct dentry *direntry, unsigned int flags) { + struct inode *inode; + if (flags & LOOKUP_RCU) return -ECHILD;
if (d_really_is_positive(direntry)) { + inode = d_inode(direntry); + if ((flags & LOOKUP_REVAL) && !CIFS_CACHE_READ(CIFS_I(inode))) + CIFS_I(inode)->time = 0; /* force reval */ + if (cifs_revalidate_dentry(direntry)) return 0; else { @@ -855,7 +861,7 @@ cifs_d_revalidate(struct dentry *direntr * attributes will have been updated by * cifs_revalidate_dentry(). */ - if (IS_AUTOMOUNT(d_inode(direntry)) && + if (IS_AUTOMOUNT(inode) && !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) { spin_lock(&direntry->d_lock); direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
From: Michal Hocko mhocko@suse.com
commit b0f53dbc4bc4c371f38b14c391095a3bb8a0bb40 upstream.
Partially revert 16db3d3f1170 ("kernel/sysctl.c: threads-max observe limits") because the patch is causing a regression to any workload which needs to override the auto-tuning of the limit provided by kernel.
set_max_threads is implementing a boot time guesstimate to provide a sensible limit of the concurrently running threads so that runaways will not deplete all the memory. This is a good thing in general but there are workloads which might need to increase this limit for an application to run (reportedly WebSpher MQ is affected) and that is simply not possible after the mentioned change. It is also very dubious to override an admin decision by an estimation that doesn't have any direct relation to correctness of the kernel operation.
Fix this by dropping set_max_threads from sysctl_max_threads so any value is accepted as long as it fits into MAX_THREADS which is important to check because allowing more threads could break internal robust futex restriction. While at it, do not use MIN_THREADS as the lower boundary because it is also only a heuristic for automatic estimation and admin might have a good reason to stop new threads to be created even when below this limit.
This became more severe when we switched x86 from 4k to 8k kernel stacks. Starting since 6538b8ea886e ("x86_64: expand kernel stack to 16K") (3.16) we use THREAD_SIZE_ORDER = 2 and that halved the auto-tuned value.
In the particular case
3.12 kernel.threads-max = 515561
4.4 kernel.threads-max = 200000
Neither of the two values is really insane on 32GB machine.
I am not sure we want/need to tune the max_thread value further. If anything the tuning should be removed altogether if proven not useful in general. But we definitely need a way to override this auto-tuning.
Link: http://lkml.kernel.org/r/20190922065801.GB18814@dhcp22.suse.cz Fixes: 16db3d3f1170 ("kernel/sysctl.c: threads-max observe limits") Signed-off-by: Michal Hocko mhocko@suse.com Reviewed-by: "Eric W. Biederman" ebiederm@xmission.com Cc: Heinrich Schuchardt xypron.glpk@gmx.de Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/fork.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/kernel/fork.c +++ b/kernel/fork.c @@ -2499,7 +2499,7 @@ int sysctl_max_threads(struct ctl_table struct ctl_table t; int ret; int threads = max_threads; - int min = MIN_THREADS; + int min = 1; int max = MAX_THREADS;
t = *table; @@ -2511,7 +2511,7 @@ int sysctl_max_threads(struct ctl_table if (ret || !write) return ret;
- set_max_threads(threads); + max_threads = threads;
return 0; }
From: Brian Norris briannorris@chromium.org
[ Upstream commit 442f1e746e8187b9deb1590176f6b0ff19686b11 ]
Commit 4b708b7b1a2c ("firmware: google: check if size is valid when decoding VPD data") adds length checks, but the new vpd_decode_entry() function botched the logic -- it adds the key length twice, instead of adding the key and value lengths separately.
On my local system, this means vpd.c's vpd_section_create_attribs() hits an error case after the first attribute it parses, since it's no longer looking at the correct offset. With this patch, I'm back to seeing all the correct attributes in /sys/firmware/vpd/...
Fixes: 4b708b7b1a2c ("firmware: google: check if size is valid when decoding VPD data") Cc: stable@vger.kernel.org Cc: Hung-Te Lin hungte@chromium.org Signed-off-by: Brian Norris briannorris@chromium.org Reviewed-by: Stephen Boyd swboyd@chromium.org Reviewed-by: Guenter Roeck groeck@chromium.org Link: https://lore.kernel.org/r/20190930214522.240680-1-briannorris@chromium.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/google/vpd_decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/google/vpd_decode.c b/drivers/firmware/google/vpd_decode.c index e75abe9fa122c..6c7ab2ba85d2f 100644 --- a/drivers/firmware/google/vpd_decode.c +++ b/drivers/firmware/google/vpd_decode.c @@ -62,7 +62,7 @@ static int vpd_decode_entry(const u32 max_len, const u8 *input_buf, if (max_len - consumed < *entry_len) return VPD_FAIL;
- consumed += decoded_len; + consumed += *entry_len; *_consumed = consumed; return VPD_OK; }
From: Bartosz Golaszewski bgolaszewski@baylibre.com
[ Upstream commit e735244e2cf068f98b6384681a38993e0517a838 ]
When emulating open-drain/open-source by not actively driving the output lines - we're simply changing their mode to input. This is wrong as it will then make it impossible to change the value of such line - it's now considered to actually be in input mode. If we want to still use the direction_input() callback for simplicity then we need to set FLAG_IS_OUT manually in gpiod_direction_output() and not clear it in gpio_set_open_drain_value_commit() and gpio_set_open_source_value_commit().
Fixes: c663e5f56737 ("gpio: support native single-ended hardware drivers") Cc: stable@vger.kernel.org Reported-by: Kent Gibson warthog618@gmail.com Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com [Bartosz: backported to v4.14] Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpio/gpiolib.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f1809a54fceeb..c7f5f0be2d749 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2329,8 +2329,10 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) if (!ret) goto set_output_value; /* Emulate open drain by not actively driving the line high */ - if (val) - return gpiod_direction_input(desc); + if (val) { + ret = gpiod_direction_input(desc); + goto set_output_flag; + } } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), @@ -2338,8 +2340,10 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) if (!ret) goto set_output_value; /* Emulate open source by not actively driving the line low */ - if (!val) - return gpiod_direction_input(desc); + if (!val) { + ret = gpiod_direction_input(desc); + goto set_output_flag; + } } else { gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), PIN_CONFIG_DRIVE_PUSH_PULL); @@ -2359,6 +2363,17 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) trace_gpio_value(desc_to_gpio(desc), 0, val); trace_gpio_direction(desc_to_gpio(desc), 0, ret); return ret; + +set_output_flag: + /* + * When emulating open-source or open-drain functionalities by not + * actively driving the line (setting mode to input) we still need to + * set the IS_OUT flag or otherwise we won't be able to set the line + * value anymore. + */ + if (ret == 0) + set_bit(FLAG_IS_OUT, &desc->flags); + return ret; }
/** @@ -2540,8 +2555,6 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value)
if (value) { err = chip->direction_input(chip, offset); - if (!err) - clear_bit(FLAG_IS_OUT, &desc->flags); } else { err = chip->direction_output(chip, offset, 0); if (!err) @@ -2571,8 +2584,6 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value) set_bit(FLAG_IS_OUT, &desc->flags); } else { err = chip->direction_input(chip, offset); - if (!err) - clear_bit(FLAG_IS_OUT, &desc->flags); } trace_gpio_direction(desc_to_gpio(desc), !value, err); if (err < 0)
From: Navid Emamdoost navid.emamdoost@gmail.com
[ Upstream commit 5bdea6060618cfcf1459dca137e89aee038ac8b9 ]
In fbtft_framebuffer_alloc the error handling path should take care of releasing frame buffer after it is allocated via framebuffer_alloc, too. Therefore, in two failure cases the goto destination is changed to address this issue.
Fixes: c296d5f9957c ("staging: fbtft: core support") Signed-off-by: Navid Emamdoost navid.emamdoost@gmail.com Reviewed-by: Dan Carpenter dan.carpenter@gmail.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20190930030949.28615-1-navid.emamdoost@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/fbtft/fbtft-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 6d0363deba619..0cbcbad8f0742 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -828,7 +828,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, if (par->gamma.curves && gamma) { if (fbtft_gamma_parse_str(par, par->gamma.curves, gamma, strlen(gamma))) - goto alloc_fail; + goto release_framebuf; }
/* Transmit buffer */ @@ -845,7 +845,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, if (txbuflen > 0) { txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL); if (!txbuf) - goto alloc_fail; + goto release_framebuf; par->txbuf.buf = txbuf; par->txbuf.len = txbuflen; } @@ -881,6 +881,9 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
return info;
+release_framebuf: + framebuffer_release(info); + alloc_fail: vfree(vmem);
From: Andreas Klinger ak@it-klinger.de
[ Upstream commit 461631face58054c72b1f1453f2d66d71b1974e7 ]
On a system with parasitic capacitance it turned out that DOUT is not ready after 100 ns after PD_SCK has raised. A measurement showed almost 1000 ns until DOUT has reached its correct value.
With this patch its now possible to wait until data is ready.
The wait time should not be higher than the maximum PD_SCK high time which is corresponding to the datasheet 50000 ns.
Signed-off-by: Andreas Klinger ak@it-klinger.de Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/adc/hx711.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 27005d84ed73d..8eb3f1bbe332b 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -89,6 +89,14 @@ struct hx711_data { int gain_set; /* gain set on device */ int gain_chan_a; /* gain for channel A */ struct mutex lock; + /* + * delay after a rising edge on SCK until the data is ready DOUT + * this is dependent on the hx711 where the datasheet tells a + * maximum value of 100 ns + * but also on potential parasitic capacities on the wiring + */ + u32 data_ready_delay_ns; + u32 clock_frequency; };
static int hx711_cycle(struct hx711_data *hx711_data) @@ -102,6 +110,14 @@ static int hx711_cycle(struct hx711_data *hx711_data) */ preempt_disable(); gpiod_set_value(hx711_data->gpiod_pd_sck, 1); + + /* + * wait until DOUT is ready + * it turned out that parasitic capacities are extending the time + * until DOUT has reached it's value + */ + ndelay(hx711_data->data_ready_delay_ns); + val = gpiod_get_value(hx711_data->gpiod_dout); /* * here we are not waiting for 0.2 us as suggested by the datasheet, @@ -112,6 +128,12 @@ static int hx711_cycle(struct hx711_data *hx711_data) gpiod_set_value(hx711_data->gpiod_pd_sck, 0); preempt_enable();
+ /* + * make it a square wave for addressing cases with capacitance on + * PC_SCK + */ + ndelay(hx711_data->data_ready_delay_ns); + return val; }
@@ -401,6 +423,7 @@ static const struct iio_chan_spec hx711_chan_spec[] = { static int hx711_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct hx711_data *hx711_data; struct iio_dev *indio_dev; int ret; @@ -474,6 +497,22 @@ static int hx711_probe(struct platform_device *pdev) hx711_data->gain_set = 128; hx711_data->gain_chan_a = 128;
+ hx711_data->clock_frequency = 400000; + ret = of_property_read_u32(np, "clock-frequency", + &hx711_data->clock_frequency); + + /* + * datasheet says the high level of PD_SCK has a maximum duration + * of 50 microseconds + */ + if (hx711_data->clock_frequency < 20000) { + dev_warn(dev, "clock-frequency too low - assuming 400 kHz\n"); + hx711_data->clock_frequency = 400000; + } + + hx711_data->data_ready_delay_ns = + 1000000000 / hx711_data->clock_frequency; + platform_set_drvdata(pdev, indio_dev);
indio_dev->name = "hx711";
From: Andreas Klinger ak@it-klinger.de
[ Upstream commit 4043ecfb5fc4355a090111e14faf7945ff0fdbd5 ]
Fix bug in sampling function hx711_cycle() when interrupt occures while PD_SCK is high. If PD_SCK is high for at least 60 us power down mode of the sensor is entered which in turn leads to a wrong measurement.
Switch off interrupts during a PD_SCK high period and move query of DOUT to the latest point of time which is at the end of PD_SCK low period.
This bug exists in the driver since it's initial addition. The more interrupts on the system the higher is the probability that it happens.
Fixes: c3b2fdd0ea7e ("iio: adc: hx711: Add IIO driver for AVIA HX711") Signed-off-by: Andreas Klinger ak@it-klinger.de Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/adc/hx711.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 8eb3f1bbe332b..0dec733471d56 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -101,14 +101,14 @@ struct hx711_data {
static int hx711_cycle(struct hx711_data *hx711_data) { - int val; + unsigned long flags;
/* * if preempted for more then 60us while PD_SCK is high: * hx711 is going in reset * ==> measuring is false */ - preempt_disable(); + local_irq_save(flags); gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
/* @@ -118,7 +118,6 @@ static int hx711_cycle(struct hx711_data *hx711_data) */ ndelay(hx711_data->data_ready_delay_ns);
- val = gpiod_get_value(hx711_data->gpiod_dout); /* * here we are not waiting for 0.2 us as suggested by the datasheet, * because the oscilloscope showed in a test scenario @@ -126,7 +125,7 @@ static int hx711_cycle(struct hx711_data *hx711_data) * and 0.56 us for PD_SCK low on TI Sitara with 800 MHz */ gpiod_set_value(hx711_data->gpiod_pd_sck, 0); - preempt_enable(); + local_irq_restore(flags);
/* * make it a square wave for addressing cases with capacitance on @@ -134,7 +133,8 @@ static int hx711_cycle(struct hx711_data *hx711_data) */ ndelay(hx711_data->data_ready_delay_ns);
- return val; + /* sample as late as possible */ + return gpiod_get_value(hx711_data->gpiod_dout); }
static int hx711_read(struct hx711_data *hx711_data)
From: Josef Bacik josef@toxicpanda.com
commit 4203e968947071586a98b5314fd7ffdea3b4f971 upstream.
We've historically had reports of being unable to mount file systems because the tree log root couldn't be read. Usually this is the "parent transid failure", but could be any of the related errors, including "fsid mismatch" or "bad tree block", depending on which block got allocated.
The modification of the individual log root items are serialized on the per-log root root_mutex. This means that any modification to the per-subvol log root_item is completely protected.
However we update the root item in the log root tree outside of the log root tree log_mutex. We do this in order to allow multiple subvolumes to be updated in each log transaction.
This is problematic however because when we are writing the log root tree out we update the super block with the _current_ log root node information. Since these two operations happen independently of each other, you can end up updating the log root tree in between writing out the dirty blocks and setting the super block to point at the current root.
This means we'll point at the new root node that hasn't been written out, instead of the one we should be pointing at. Thus whatever garbage or old block we end up pointing at complains when we mount the file system later and try to replay the log.
Fix this by copying the log's root item into a local root item copy. Then once we're safely under the log_root_tree->log_mutex we update the root item in the log_root_tree. This way we do not modify the log_root_tree while we're committing it, fixing the problem.
CC: stable@vger.kernel.org # 4.4+ Reviewed-by: Chris Mason clm@fb.com Reviewed-by: Filipe Manana fdmanana@suse.com Signed-off-by: Josef Bacik josef@toxicpanda.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/btrfs/tree-log.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-)
--- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -2729,7 +2729,8 @@ out: * in the tree of log roots */ static int update_log_root(struct btrfs_trans_handle *trans, - struct btrfs_root *log) + struct btrfs_root *log, + struct btrfs_root_item *root_item) { struct btrfs_fs_info *fs_info = log->fs_info; int ret; @@ -2737,10 +2738,10 @@ static int update_log_root(struct btrfs_ if (log->log_transid == 1) { /* insert root item on the first sync */ ret = btrfs_insert_root(trans, fs_info->log_root_tree, - &log->root_key, &log->root_item); + &log->root_key, root_item); } else { ret = btrfs_update_root(trans, fs_info->log_root_tree, - &log->root_key, &log->root_item); + &log->root_key, root_item); } return ret; } @@ -2836,6 +2837,7 @@ int btrfs_sync_log(struct btrfs_trans_ha struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *log = root->log_root; struct btrfs_root *log_root_tree = fs_info->log_root_tree; + struct btrfs_root_item new_root_item; int log_transid = 0; struct btrfs_log_ctx root_log_ctx; struct blk_plug plug; @@ -2901,18 +2903,26 @@ int btrfs_sync_log(struct btrfs_trans_ha goto out; }
+ /* + * We _must_ update under the root->log_mutex in order to make sure we + * have a consistent view of the log root we are trying to commit at + * this moment. + * + * We _must_ copy this into a local copy, because we are not holding the + * log_root_tree->log_mutex yet. This is important because when we + * commit the log_root_tree we must have a consistent view of the + * log_root_tree when we update the super block to point at the + * log_root_tree bytenr. If we update the log_root_tree here we'll race + * with the commit and possibly point at the new block which we may not + * have written out. + */ btrfs_set_root_node(&log->root_item, log->node); + memcpy(&new_root_item, &log->root_item, sizeof(new_root_item));
root->log_transid++; log->log_transid = root->log_transid; root->log_start_pid = 0; /* - * Update or create log root item under the root's log_mutex to prevent - * races with concurrent log syncs that can lead to failure to update - * log root item because it was not created yet. - */ - ret = update_log_root(trans, log); - /* * IO has been started, blocks of the log tree have WRITTEN flag set * in their headers. new modifications of the log will be written to * new positions. so it's safe to allow log writers to go in. @@ -2932,6 +2942,14 @@ int btrfs_sync_log(struct btrfs_trans_ha mutex_unlock(&log_root_tree->log_mutex);
mutex_lock(&log_root_tree->log_mutex); + + /* + * Now we are safe to update the log_root_tree because we're under the + * log_mutex, and we're a current writer so we're holding the commit + * open until we drop the log_mutex. + */ + ret = update_log_root(trans, log, &new_root_item); + if (atomic_dec_and_test(&log_root_tree->log_writers)) { /* * Implicit memory barrier after atomic_dec_and_test
From: Trond Myklebust trondmy@gmail.com
commit 031d73ed768a40684f3ca21992265ffdb6a270bf upstream.
When a series of O_DIRECT reads or writes are truncated, either due to eof or due to an error, then we should return the number of contiguous bytes that were received/sent starting at the offset specified by the application.
Currently, we are failing to correctly check contiguity, and so we're failing the generic/465 in xfstests when the race between the read and write RPCs causes the file to get extended while the 2 reads are outstanding. If the first read RPC call wins the race and returns with eof set, we should treat the second read RPC as being truncated.
Reported-by: Su Yanjun suyj.fnst@cn.fujitsu.com Fixes: 1ccbad9f9f9bd ("nfs: fix DIO good bytes calculation") Cc: stable@vger.kernel.org # 4.1+ Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/nfs/direct.c | 78 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 35 deletions(-)
--- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -122,32 +122,49 @@ static inline int put_dreq(struct nfs_di }
static void -nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr) +nfs_direct_handle_truncated(struct nfs_direct_req *dreq, + const struct nfs_pgio_header *hdr, + ssize_t dreq_len) +{ + struct nfs_direct_mirror *mirror = &dreq->mirrors[hdr->pgio_mirror_idx]; + + if (!(test_bit(NFS_IOHDR_ERROR, &hdr->flags) || + test_bit(NFS_IOHDR_EOF, &hdr->flags))) + return; + if (dreq->max_count >= dreq_len) { + dreq->max_count = dreq_len; + if (dreq->count > dreq_len) + dreq->count = dreq_len; + + if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) + dreq->error = hdr->error; + else /* Clear outstanding error if this is EOF */ + dreq->error = 0; + } + if (mirror->count > dreq_len) + mirror->count = dreq_len; +} + +static void +nfs_direct_count_bytes(struct nfs_direct_req *dreq, + const struct nfs_pgio_header *hdr) { - int i; - ssize_t count; + struct nfs_direct_mirror *mirror = &dreq->mirrors[hdr->pgio_mirror_idx]; + loff_t hdr_end = hdr->io_start + hdr->good_bytes; + ssize_t dreq_len = 0;
- WARN_ON_ONCE(dreq->count >= dreq->max_count); + if (hdr_end > dreq->io_start) + dreq_len = hdr_end - dreq->io_start;
- if (dreq->mirror_count == 1) { - dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes; - dreq->count += hdr->good_bytes; - } else { - /* mirrored writes */ - count = dreq->mirrors[hdr->pgio_mirror_idx].count; - if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) { - count = hdr->io_start + hdr->good_bytes - dreq->io_start; - dreq->mirrors[hdr->pgio_mirror_idx].count = count; - } - /* update the dreq->count by finding the minimum agreed count from all - * mirrors */ - count = dreq->mirrors[0].count; + nfs_direct_handle_truncated(dreq, hdr, dreq_len);
- for (i = 1; i < dreq->mirror_count; i++) - count = min(count, dreq->mirrors[i].count); + if (dreq_len > dreq->max_count) + dreq_len = dreq->max_count;
- dreq->count = count; - } + if (mirror->count < dreq_len) + mirror->count = dreq_len; + if (dreq->count < dreq_len) + dreq->count = dreq_len; }
/* @@ -401,20 +418,12 @@ static void nfs_direct_read_completion(s struct nfs_direct_req *dreq = hdr->dreq;
spin_lock(&dreq->lock); - if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) - dreq->error = hdr->error; - if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) { spin_unlock(&dreq->lock); goto out_put; }
- if (hdr->good_bytes != 0) - nfs_direct_good_bytes(dreq, hdr); - - if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) - dreq->error = 0; - + nfs_direct_count_bytes(dreq, hdr); spin_unlock(&dreq->lock);
while (!list_empty(&hdr->pages)) { @@ -651,6 +660,9 @@ static void nfs_direct_write_reschedule( nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
dreq->count = 0; + dreq->max_count = 0; + list_for_each_entry(req, &reqs, wb_list) + dreq->max_count += req->wb_bytes; dreq->verf.committed = NFS_INVALID_STABLE_HOW; nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo); for (i = 0; i < dreq->mirror_count; i++) @@ -783,17 +795,13 @@ static void nfs_direct_write_completion( nfs_init_cinfo_from_dreq(&cinfo, dreq);
spin_lock(&dreq->lock); - - if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) - dreq->error = hdr->error; - if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) { spin_unlock(&dreq->lock); goto out_put; }
+ nfs_direct_count_bytes(dreq, hdr); if (hdr->good_bytes != 0) { - nfs_direct_good_bytes(dreq, hdr); if (nfs_write_need_commit(hdr)) { if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) request_commit = true;
From: Paul Burton paul.burton@mips.com
commit 2f2b4fd674cadd8c6b40eb629e140a14db4068fd upstream.
GCC 9.x automatically enables support for Loongson MMI instructions when using some -march= flags, and then errors out when -msoft-float is specified with:
cc1: error: ‘-mloongson-mmi’ must be used with ‘-mhard-float’
The kernel shouldn't be using these MMI instructions anyway, just as it doesn't use floating point instructions. Explicitly disable them in order to fix the build with GCC 9.x.
Signed-off-by: Paul Burton paul.burton@mips.com Fixes: 3702bba5eb4f ("MIPS: Loongson: Add GCC 4.4 support for Loongson2E") Fixes: 6f7a251a259e ("MIPS: Loongson: Add basic Loongson 2F support") Fixes: 5188129b8c9f ("MIPS: Loongson-3: Improve -march option and move it to Platform") Cc: Huacai Chen chenhc@lemote.com Cc: Jiaxun Yang jiaxun.yang@flygoat.com Cc: stable@vger.kernel.org # v2.6.32+ Cc: linux-mips@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/mips/loongson64/Platform | 4 ++++ arch/mips/vdso/Makefile | 1 + 2 files changed, 5 insertions(+)
--- a/arch/mips/loongson64/Platform +++ b/arch/mips/loongson64/Platform @@ -43,6 +43,10 @@ else $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) endif
+# Some -march= flags enable MMI instructions, and GCC complains about that +# support being enabled alongside -msoft-float. Thus explicitly disable MMI. +cflags-y += $(call cc-option,-mno-loongson-mmi) + # # Loongson Machines' Support # --- a/arch/mips/vdso/Makefile +++ b/arch/mips/vdso/Makefile @@ -9,6 +9,7 @@ ccflags-vdso := \ $(filter -mmicromips,$(KBUILD_CFLAGS)) \ $(filter -march=%,$(KBUILD_CFLAGS)) \ $(filter -m%-float,$(KBUILD_CFLAGS)) \ + $(filter -mno-loongson-%,$(KBUILD_CFLAGS)) \ -D__VDSO__ cflags-vdso := $(ccflags-vdso) \ $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
From: Al Viro viro@zeniv.linux.org.uk
commit d4f4de5e5ef8efde85febb6876cd3c8ab1631999 upstream.
There are two problems in dcache_readdir() - one is that lockless traversal of the list needs non-trivial cooperation of d_alloc() (at least a switch to list_add_rcu(), and probably more than just that) and another is that it assumes that no removal will happen without the directory locked exclusive. Said assumption had always been there, never had been stated explicitly and is violated by several places in the kernel (devpts and selinuxfs).
* replacement of next_positive() with different calling conventions: it returns struct list_head * instead of struct dentry *; the latter is passed in and out by reference, grabbing the result and dropping the original value. * scan is under ->d_lock. If we run out of timeslice, cursor is moved after the last position we'd reached and we reschedule; then the scan continues from that place. To avoid livelocks between multiple lseek() (with cursors getting moved past each other, never reaching the real entries) we always skip the cursors, need_resched() or not. * returned list_head * is either ->d_child of dentry we'd found or ->d_subdirs of parent (if we got to the end of the list). * dcache_readdir() and dcache_dir_lseek() switched to new helper. dcache_readdir() always holds a reference to dentry passed to dir_emit() now. Cursor is moved to just before the entry where dir_emit() has failed or into the very end of the list, if we'd run out. * move_cursor() eliminated - it had sucky calling conventions and after fixing that it became simply list_move() (in lseek and scan_positives) or list_move_tail() (in readdir).
All operations with the list are under ->d_lock now, and we do not depend upon having all file removals done with parent locked exclusive anymore.
Cc: stable@vger.kernel.org Reported-by: "zhengbin (A)" zhengbin13@huawei.com Signed-off-by: Al Viro viro@zeniv.linux.org.uk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/libfs.c | 134 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 69 insertions(+), 65 deletions(-)
--- a/fs/libfs.c +++ b/fs/libfs.c @@ -86,58 +86,47 @@ int dcache_dir_close(struct inode *inode EXPORT_SYMBOL(dcache_dir_close);
/* parent is locked at least shared */ -static struct dentry *next_positive(struct dentry *parent, - struct list_head *from, - int count) +/* + * Returns an element of siblings' list. + * We are looking for <count>th positive after <p>; if + * found, dentry is grabbed and passed to caller via *<res>. + * If no such element exists, the anchor of list is returned + * and *<res> is set to NULL. + */ +static struct list_head *scan_positives(struct dentry *cursor, + struct list_head *p, + loff_t count, + struct dentry **res) { - unsigned *seq = &parent->d_inode->i_dir_seq, n; - struct dentry *res; - struct list_head *p; - bool skipped; - int i; + struct dentry *dentry = cursor->d_parent, *found = NULL;
-retry: - i = count; - skipped = false; - n = smp_load_acquire(seq) & ~1; - res = NULL; - rcu_read_lock(); - for (p = from->next; p != &parent->d_subdirs; p = p->next) { + spin_lock(&dentry->d_lock); + while ((p = p->next) != &dentry->d_subdirs) { struct dentry *d = list_entry(p, struct dentry, d_child); - if (!simple_positive(d)) { - skipped = true; - } else if (!--i) { - res = d; - break; + // we must at least skip cursors, to avoid livelocks + if (d->d_flags & DCACHE_DENTRY_CURSOR) + continue; + if (simple_positive(d) && !--count) { + spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); + if (simple_positive(d)) + found = dget_dlock(d); + spin_unlock(&d->d_lock); + if (likely(found)) + break; + count = 1; + } + if (need_resched()) { + list_move(&cursor->d_child, p); + p = &cursor->d_child; + spin_unlock(&dentry->d_lock); + cond_resched(); + spin_lock(&dentry->d_lock); } } - rcu_read_unlock(); - if (skipped) { - smp_rmb(); - if (unlikely(*seq != n)) - goto retry; - } - return res; -} - -static void move_cursor(struct dentry *cursor, struct list_head *after) -{ - struct dentry *parent = cursor->d_parent; - unsigned n, *seq = &parent->d_inode->i_dir_seq; - spin_lock(&parent->d_lock); - for (;;) { - n = *seq; - if (!(n & 1) && cmpxchg(seq, n, n + 1) == n) - break; - cpu_relax(); - } - __list_del(cursor->d_child.prev, cursor->d_child.next); - if (after) - list_add(&cursor->d_child, after); - else - list_add_tail(&cursor->d_child, &parent->d_subdirs); - smp_store_release(seq, n + 2); - spin_unlock(&parent->d_lock); + spin_unlock(&dentry->d_lock); + dput(*res); + *res = found; + return p; }
loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) @@ -153,17 +142,28 @@ loff_t dcache_dir_lseek(struct file *fil return -EINVAL; } if (offset != file->f_pos) { + struct dentry *cursor = file->private_data; + struct dentry *to = NULL; + struct list_head *p; + file->f_pos = offset; - if (file->f_pos >= 2) { - struct dentry *cursor = file->private_data; - struct dentry *to; - loff_t n = file->f_pos - 2; - - inode_lock_shared(dentry->d_inode); - to = next_positive(dentry, &dentry->d_subdirs, n); - move_cursor(cursor, to ? &to->d_child : NULL); - inode_unlock_shared(dentry->d_inode); + inode_lock_shared(dentry->d_inode); + + if (file->f_pos > 2) { + p = scan_positives(cursor, &dentry->d_subdirs, + file->f_pos - 2, &to); + spin_lock(&dentry->d_lock); + list_move(&cursor->d_child, p); + spin_unlock(&dentry->d_lock); + } else { + spin_lock(&dentry->d_lock); + list_del_init(&cursor->d_child); + spin_unlock(&dentry->d_lock); } + + dput(to); + + inode_unlock_shared(dentry->d_inode); } return offset; } @@ -185,25 +185,29 @@ int dcache_readdir(struct file *file, st { struct dentry *dentry = file->f_path.dentry; struct dentry *cursor = file->private_data; - struct list_head *p = &cursor->d_child; - struct dentry *next; - bool moved = false; + struct list_head *anchor = &dentry->d_subdirs; + struct dentry *next = NULL; + struct list_head *p;
if (!dir_emit_dots(file, ctx)) return 0;
if (ctx->pos == 2) - p = &dentry->d_subdirs; - while ((next = next_positive(dentry, p, 1)) != NULL) { + p = anchor; + else + p = &cursor->d_child; + + while ((p = scan_positives(cursor, p, 1, &next)) != anchor) { if (!dir_emit(ctx, next->d_name.name, next->d_name.len, d_inode(next)->i_ino, dt_type(d_inode(next)))) break; - moved = true; - p = &next->d_child; ctx->pos++; } - if (moved) - move_cursor(cursor, p); + spin_lock(&dentry->d_lock); + list_move_tail(&cursor->d_child, p); + spin_unlock(&dentry->d_lock); + dput(next); + return 0; } EXPORT_SYMBOL(dcache_readdir);
From: Johan Hovold johan@kernel.org
commit 30045f2174aab7fb4db7a9cf902d0aa6c75856a7 upstream.
Since commit c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") USB drivers must always balance their runtime PM gets and puts, including when the driver has already been unbound from the interface.
Leaving the interface with a positive PM usage counter would prevent a later bound driver from suspending the device.
Note that runtime PM has never actually been enabled for this driver since the support_autosuspend flag in its usb_driver struct is not set.
Fixes: c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") Cc: stable stable@vger.kernel.org Acked-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191001084908.2003-5-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/usb/stkwebcam/stk-webcam.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -640,8 +640,7 @@ static int v4l_stk_release(struct file * dev->owner = NULL; }
- if (is_present(dev)) - usb_autopm_put_interface(dev->interface); + usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->lock); return v4l2_fh_release(fp); }
From: Srivatsa S. Bhat (VMware) srivatsa@csail.mit.edu
commit 98dc19c11470ee6048aba723d77079ad2cda8a52 upstream.
nmi_total_ts is supposed to record the total time spent in *all* NMIs that occur on the given CPU during the (active portion of the) sampling window. However, the code seems to be overwriting this variable for each NMI, thereby only recording the time spent in the most recent NMI. Fix it by accumulating the duration instead.
Link: http://lkml.kernel.org/r/157073343544.17189.13911783866738671133.stgit@sriva...
Fixes: 7b2c86250122 ("tracing: Add NMI tracing in hwlat detector") Cc: stable@vger.kernel.org Signed-off-by: Srivatsa S. Bhat (VMware) srivatsa@csail.mit.edu Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/trace/trace_hwlat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -152,7 +152,7 @@ void trace_hwlat_callback(bool enter) if (enter) nmi_ts_start = time_get(); else - nmi_total_ts = time_get() - nmi_ts_start; + nmi_total_ts += time_get() - nmi_ts_start; }
if (enter)
From: Srivatsa S. Bhat (VMware) srivatsa@csail.mit.edu
commit fc64e4ad80d4b72efce116f87b3174f0b7196f8e upstream.
max_latency is intended to record the maximum ever observed hardware latency, which may occur in either part of the loop (inner/outer). So we need to also consider the outer-loop sample when updating max_latency.
Link: http://lkml.kernel.org/r/157073345463.17189.18124025522664682811.stgit@sriva...
Fixes: e7c15cd8a113 ("tracing: Added hardware latency tracer") Cc: stable@vger.kernel.org Signed-off-by: Srivatsa S. Bhat (VMware) srivatsa@csail.mit.edu Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/trace/trace_hwlat.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -258,6 +258,8 @@ static int get_sample(void) /* Keep a running maximum ever recorded hardware latency */ if (sample > tr->max_latency) tr->max_latency = sample; + if (outer_sample > tr->max_latency) + tr->max_latency = outer_sample; }
out:
From: Steven Rostedt (VMware) rostedt@goodmis.org
commit 9ef16693aff8137faa21d16ffe65bb9832d24d71 upstream.
The ftrace set_ftrace_filter and set_ftrace_notrace files are specific for an instance now. They need to take a reference to the instance otherwise there could be a race between accessing the files and deleting the instance.
It wasn't until the :mod: caching where these file operations started referencing the trace_array directly.
Cc: stable@vger.kernel.org Fixes: 673feb9d76ab3 ("ftrace: Add :mod: caching infrastructure to trace_array") Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/trace/ftrace.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
--- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3629,21 +3629,22 @@ ftrace_regex_open(struct ftrace_ops *ops struct ftrace_hash *hash; struct list_head *mod_head; struct trace_array *tr = ops->private; - int ret = 0; + int ret = -ENOMEM;
ftrace_ops_init(ops);
if (unlikely(ftrace_disabled)) return -ENODEV;
+ if (tr && trace_array_get(tr) < 0) + return -ENODEV; + iter = kzalloc(sizeof(*iter), GFP_KERNEL); if (!iter) - return -ENOMEM; + goto out;
- if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) { - kfree(iter); - return -ENOMEM; - } + if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) + goto out;
iter->ops = ops; iter->flags = flag; @@ -3673,13 +3674,13 @@ ftrace_regex_open(struct ftrace_ops *ops
if (!iter->hash) { trace_parser_put(&iter->parser); - kfree(iter); - ret = -ENOMEM; goto out_unlock; } } else iter->hash = hash;
+ ret = 0; + if (file->f_mode & FMODE_READ) { iter->pg = ftrace_pages_start;
@@ -3691,7 +3692,6 @@ ftrace_regex_open(struct ftrace_ops *ops /* Failed */ free_ftrace_hash(iter->hash); trace_parser_put(&iter->parser); - kfree(iter); } } else file->private_data = iter; @@ -3699,6 +3699,13 @@ ftrace_regex_open(struct ftrace_ops *ops out_unlock: mutex_unlock(&ops->func_hash->regex_lock);
+ out: + if (ret) { + kfree(iter); + if (tr) + trace_array_put(tr); + } + return ret; }
@@ -5098,6 +5105,8 @@ int ftrace_regex_release(struct inode *i
mutex_unlock(&iter->ops->func_hash->regex_lock); free_ftrace_hash(iter->hash); + if (iter->tr) + trace_array_put(iter->tr); kfree(iter);
return 0;
From: Steven Rostedt (VMware) rostedt@goodmis.org
commit 194c2c74f5532e62c218adeb8e2b683119503907 upstream.
As instances may have different tracers available, we need to look at the trace_array descriptor that shows the list of the available tracers for the instance. But there's a race between opening the file and an admin deleting the instance. The trace_array_get() needs to be called before accessing the trace_array.
Cc: stable@vger.kernel.org Fixes: 607e2ea167e56 ("tracing: Set up infrastructure to allow tracers for instances") Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/trace/trace.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
--- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4152,9 +4152,14 @@ static int show_traces_open(struct inode if (tracing_disabled) return -ENODEV;
+ if (trace_array_get(tr) < 0) + return -ENODEV; + ret = seq_open(file, &show_traces_seq_ops); - if (ret) + if (ret) { + trace_array_put(tr); return ret; + }
m = file->private_data; m->private = tr; @@ -4162,6 +4167,14 @@ static int show_traces_open(struct inode return 0; }
+static int show_traces_release(struct inode *inode, struct file *file) +{ + struct trace_array *tr = inode->i_private; + + trace_array_put(tr); + return seq_release(inode, file); +} + static ssize_t tracing_write_stub(struct file *filp, const char __user *ubuf, size_t count, loff_t *ppos) @@ -4192,8 +4205,8 @@ static const struct file_operations trac static const struct file_operations show_traces_fops = { .open = show_traces_open, .read = seq_read, - .release = seq_release, .llseek = seq_lseek, + .release = show_traces_release, };
static ssize_t
From: Janakarajan Natarajan Janakarajan.Natarajan@amd.com
commit 454de1e7d970d6bc567686052329e4814842867c upstream.
As per "AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions", MWAITX EAX[7:4]+1 specifies the optional hint of the optimized C-state. For C0 state, EAX[7:4] should be set to 0xf.
Currently, a value of 0xf is set for EAX[3:0] instead of EAX[7:4]. Fix this by changing MWAITX_DISABLE_CSTATES from 0xf to 0xf0.
This hasn't had any implications so far because setting reserved bits in EAX is simply ignored by the CPU.
[ bp: Fixup comment in delay_mwaitx() and massage. ]
Signed-off-by: Janakarajan Natarajan Janakarajan.Natarajan@amd.com Signed-off-by: Borislav Petkov bp@suse.de Cc: Frederic Weisbecker frederic@kernel.org Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: "H. Peter Anvin" hpa@zytor.com Cc: Ingo Molnar mingo@redhat.com Cc: Thomas Gleixner tglx@linutronix.de Cc: "x86@kernel.org" x86@kernel.org Cc: Zhenzhong Duan zhenzhong.duan@oracle.com Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20191007190011.4859-1-Janakarajan.Natarajan@amd.co... Signed-off-by: Ingo Molnar mingo@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/include/asm/mwait.h | 2 +- arch/x86/lib/delay.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
--- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -21,7 +21,7 @@ #define MWAIT_ECX_INTERRUPT_BREAK 0x1 #define MWAITX_ECX_TIMER_ENABLE BIT(1) #define MWAITX_MAX_LOOPS ((u32)-1) -#define MWAITX_DISABLE_CSTATES 0xf +#define MWAITX_DISABLE_CSTATES 0xf0
static inline void __monitor(const void *eax, unsigned long ecx, unsigned long edx) --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c @@ -113,8 +113,8 @@ static void delay_mwaitx(unsigned long _ __monitorx(raw_cpu_ptr(&cpu_tss_rw), 0, 0);
/* - * AMD, like Intel, supports the EAX hint and EAX=0xf - * means, do not enter any deep C-state and we use it + * AMD, like Intel's MWAIT version, supports the EAX hint and + * EAX=0xf0 means, do not enter any deep C-state and we use it * here in delay() to minimize wakeup latency. */ __mwaitx(MWAITX_DISABLE_CSTATES, delay, MWAITX_ECX_TIMER_ENABLE);
From: Dave Chinner dchinner@redhat.com
commit c9fbd7bbc23dbdd73364be4d045e5d3612cf6e82 upstream.
We recently had an oops reported on a 4.14 kernel in xfs_reclaim_inodes_count() where sb->s_fs_info pointed to garbage and so the m_perag_tree lookup walked into lala land.
Essentially, the machine was under memory pressure when the mount was being run, xfs_fs_fill_super() failed after allocating the xfs_mount and attaching it to sb->s_fs_info. It then cleaned up and freed the xfs_mount, but the sb->s_fs_info field still pointed to the freed memory. Hence when the superblock shrinker then ran it fell off the bad pointer.
With the superblock shrinker problem fixed at teh VFS level, this stale s_fs_info pointer is still a problem - we use it unconditionally in ->put_super when the superblock is being torn down, and hence we can still trip over it after a ->fill_super call failure. Hence we need to clear s_fs_info if xfs-fs_fill_super() fails, and we need to check if it's valid in the places it can potentially be dereferenced after a ->fill_super failure.
Signed-Off-By: Dave Chinner dchinner@redhat.com Reviewed-by: Darrick J. Wong darrick.wong@oracle.com Signed-off-by: Darrick J. Wong darrick.wong@oracle.com Signed-off-by: Ajay Kaher akaher@vmware.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/xfs_super.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
--- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1715,6 +1715,7 @@ xfs_fs_fill_super( out_close_devices: xfs_close_devices(mp); out_free_fsname: + sb->s_fs_info = NULL; xfs_free_fsname(mp); kfree(mp); out: @@ -1732,6 +1733,10 @@ xfs_fs_put_super( { struct xfs_mount *mp = XFS_M(sb);
+ /* if ->fill_super failed, we have no mount to tear down */ + if (!sb->s_fs_info) + return; + xfs_notice(mp, "Unmounting Filesystem"); xfs_filestream_unmount(mp); xfs_unmountfs(mp); @@ -1741,6 +1746,8 @@ xfs_fs_put_super( xfs_destroy_percpu_counters(mp); xfs_destroy_mount_workqueues(mp); xfs_close_devices(mp); + + sb->s_fs_info = NULL; xfs_free_fsname(mp); kfree(mp); } @@ -1760,6 +1767,9 @@ xfs_fs_nr_cached_objects( struct super_block *sb, struct shrink_control *sc) { + /* Paranoia: catch incorrect calls during mount setup or teardown */ + if (WARN_ON_ONCE(!sb->s_fs_info)) + return 0; return xfs_reclaim_inodes_count(XFS_M(sb)); }
stable-rc/linux-4.14.y boot: 104 boots: 1 failed, 97 passed with 6 offline (v4.14.149-65-gb29fcefccab6)
Full Boot Summary: https://kernelci.org/boot/all/job/stable-rc/branch/linux-4.14.y/kernel/v4.14... Full Build Summary: https://kernelci.org/build/stable-rc/branch/linux-4.14.y/kernel/v4.14.149-65...
Tree: stable-rc Branch: linux-4.14.y Git Describe: v4.14.149-65-gb29fcefccab6 Git Commit: b29fcefccab67589bcd5b49b74967d723e708013 Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git Tested: 60 unique boards, 21 SoC families, 13 builds out of 201
Boot Failure Detected:
arm64: defconfig: gcc-8: meson-gxbb-p200: 1 failed lab
Offline Platforms:
arm:
sunxi_defconfig: gcc-8 sun5i-r8-chip: 1 offline lab
multi_v7_defconfig: gcc-8 qcom-apq8064-cm-qs600: 1 offline lab sun5i-r8-chip: 1 offline lab sun7i-a20-bananapi: 1 offline lab
davinci_all_defconfig: gcc-8 dm365evm,legacy: 1 offline lab
qcom_defconfig: gcc-8 qcom-apq8064-cm-qs600: 1 offline lab
--- For more info write to info@kernelci.org
On Thu, 17 Oct 2019 at 03:26, Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.150-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y and the diffstat can be found below.
thanks,
greg k-h
Results from Linaro’s test farm. No regressions on arm64, arm, x86_64, and i386.
Summary ------------------------------------------------------------------------
kernel: 4.14.150-rc1 git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git git branch: linux-4.14.y git commit: 66f69184d7229bdf1ac19b8928747553ca3e5914 git describe: v4.14.149-66-g66f69184d722 Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-4.14-oe/build/v4.14.149-6...
No regressions (compared to build v4.14.149)
No fixes (compared to build v4.14.149)
Ran 23950 total tests in the following environments and test suites.
Environments -------------- - dragonboard-410c - arm64 - hi6220-hikey - arm64 - i386 - juno-r2 - arm64 - qemu_arm - qemu_arm64 - qemu_i386 - qemu_x86_64 - x15 - arm - x86_64
Test Suites ----------- * build * install-android-platform-tools-r2600 * kselftest * libhugetlbfs * ltp-cap_bounds-tests * ltp-commands-tests * ltp-containers-tests * ltp-cpuhotplug-tests * ltp-cve-tests * ltp-dio-tests * ltp-fcntl-locktests-tests * ltp-filecaps-tests * ltp-fs_bind-tests * ltp-fs_perms_simple-tests * ltp-fsx-tests * ltp-hugetlb-tests * ltp-io-tests * ltp-ipc-tests * ltp-math-tests * ltp-mm-tests * ltp-nptl-tests * ltp-pty-tests * ltp-sched-tests * ltp-securebits-tests * ltp-syscalls-tests * ltp-timers-tests * perf * spectre-meltdown-checker-test * v4l2-compliance * ltp-fs-tests * network-basic-tests * ltp-open-posix-tests * kvm-unit-tests * kselftest-vsyscall-mode-native * kselftest-vsyscall-mode-none * ssuite
On 10/16/19 3:50 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.150-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y and the diffstat can be found below.
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks, -- Shuah
On Wed, Oct 16, 2019 at 02:50:14PM -0700, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
Build results: total: 172 pass: 172 fail: 0 Qemu test results: total: 372 pass: 372 fail: 0
Guenter
On Wed, Oct 16, 2019 at 02:50:14PM -0700, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.150-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y and the diffstat can be found below.
thanks,
greg k-h
Compiled, booted, and no regressions found on my x86_64 system.
Thanks, Didik Setiawan
On 16/10/2019 22:50, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.150-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y and the diffstat can be found below.
thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v4.14: 8 builds: 8 pass, 0 fail 16 boots: 16 pass, 0 fail 24 tests: 24 pass, 0 fail
Linux version: 4.14.150-rc1-g66f69184d722 Boards tested: tegra124-jetson-tk1, tegra20-ventana, tegra210-p2371-2180, tegra30-cardhu-a04
Cheers Jon
Greg Kroah-Hartman gregkh@linuxfoundation.org 于2019年10月17日周四 下午11:56写道:
This is the start of the stable review cycle for the 4.14.150 release. There are 65 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri 18 Oct 2019 09:43:41 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.150-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y and the diffstat can be found below.
thanks,
greg k-h
Merged and tested on my test machines, no regression!
Thanks, Jack Wang
linux-stable-mirror@lists.linaro.org