This is the 4.19.80 stable release

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAl2o0vkACgkQONu9yGCS
 aT50rQ//So/ShGy5+D6cmsPVbd8p/9X0fM5D6VjgJ2pj+HbalxW7JhJ0tyVdfkO1
 AS6p/24bmUMWI3pxJBbJjfggbyleV2UFqlHIei+SjfHd0sghZ+E/XY7mLdcKvx0a
 dGdXuxF+enb18pNiUKUrJUgqksgfO40yMXyZhjGf5A+/JmYsNaJhkyCWgPfGIB5i
 YuowOWC4Rkds/CQxyRSRJl+YSQWh8j7Ke0tdjhMQxnmyzFD0wcE5vUtq2vIP7yxO
 ypPrz9zWTase3y1yCcPsXd0m4Ji1VpF99hlgAr0HLFNcZn2kNYFpyblfOrI/zfoK
 RqUJgVVlZaWvhMOrueQO+XbebXdCWTJHiNTUDxIFakEAPNz+XkTQQf6LvzOjcFxB
 oLHnp1qBCn72y6o6Q3XmauFcmYBokyfBvXDAJsXYr+X5B4akn/fpyzzBCInX0h+r
 og5zpLbXDLszG3j76TPSpcjd+t4xqMy+MG+jkH/mLtMAFyaVi2sfMzsZJAQCACr2
 wNHRFQQGjDmQjovkwSRYENQBUuITSj+VrBUD0M7lnfA/Fni3BAJaxY5I6WeEvbeW
 ejzPVFZB8dfEy7hAKKiVEuI8/akcp8MUXfLJOfTxytLIpYllOBoVC4LtjgO5FYu3
 grSbRuowjrlUCtnCU9H18avLE1ScFFEGTmPOqI6xDqKiZf59QsQ=
 =sKVA
 -----END PGP SIGNATURE-----

Merge 4.19.80 into android-4.19-q

Changes in 4.19.80
	panic: ensure preemption is disabled during panic()
	f2fs: use EINVAL for superblock with invalid magic
	USB: rio500: Remove Rio 500 kernel driver
	USB: yurex: Don't retry on unexpected errors
	USB: yurex: fix NULL-derefs on disconnect
	USB: usb-skeleton: fix runtime PM after driver unbind
	USB: usb-skeleton: fix NULL-deref on disconnect
	xhci: Fix false warning message about wrong bounce buffer write length
	xhci: Prevent device initiated U1/U2 link pm if exit latency is too long
	xhci: Check all endpoints for LPM timeout
	xhci: Fix USB 3.1 capability detection on early xHCI 1.1 spec based hosts
	usb: xhci: wait for CNR controller not ready bit in xhci resume
	xhci: Prevent deadlock when xhci adapter breaks during init
	xhci: Increase STS_SAVE timeout in xhci_suspend()
	USB: adutux: fix use-after-free on disconnect
	USB: adutux: fix NULL-derefs on disconnect
	USB: adutux: fix use-after-free on release
	USB: iowarrior: fix use-after-free on disconnect
	USB: iowarrior: fix use-after-free on release
	USB: iowarrior: fix use-after-free after driver unbind
	USB: usblp: fix runtime PM after driver unbind
	USB: chaoskey: fix use-after-free on release
	USB: ldusb: fix NULL-derefs on driver unbind
	serial: uartlite: fix exit path null pointer
	USB: serial: keyspan: fix NULL-derefs on open() and write()
	USB: serial: ftdi_sio: add device IDs for Sienna and Echelon PL-20
	USB: serial: option: add Telit FN980 compositions
	USB: serial: option: add support for Cinterion CLS8 devices
	USB: serial: fix runtime PM after driver unbind
	USB: usblcd: fix I/O after disconnect
	USB: microtek: fix info-leak at probe
	USB: dummy-hcd: fix power budget for SuperSpeed mode
	usb: renesas_usbhs: gadget: Do not discard queues in usb_ep_set_{halt,wedge}()
	usb: renesas_usbhs: gadget: Fix usb_ep_set_{halt,wedge}() behavior
	USB: legousbtower: fix slab info leak at probe
	USB: legousbtower: fix deadlock on disconnect
	USB: legousbtower: fix potential NULL-deref on disconnect
	USB: legousbtower: fix open after failed reset request
	USB: legousbtower: fix use-after-free on release
	mei: me: add comet point (lake) LP device ids
	mei: avoid FW version request on Ibex Peak and earlier
	gpio: eic: sprd: Fix the incorrect EIC offset when toggling
	Staging: fbtft: fix memory leak in fbtft_framebuffer_alloc
	staging: vt6655: Fix memory leak in vt6655_probe
	iio: adc: hx711: fix bug in sampling of data
	iio: adc: ad799x: fix probe error handling
	iio: adc: axp288: Override TS pin bias current for some models
	iio: light: opt3001: fix mutex unlock race
	efivar/ssdt: Don't iterate over EFI vars if no SSDT override was specified
	perf llvm: Don't access out-of-scope array
	perf inject jit: Fix JIT_CODE_MOVE filename
	blk-wbt: fix performance regression in wbt scale_up/scale_down
	CIFS: Gracefully handle QueryInfo errors during open
	CIFS: Force revalidate inode when dentry is stale
	CIFS: Force reval dentry if LOOKUP_REVAL flag is set
	kernel/sysctl.c: do not override max_threads provided by userspace
	mm/vmpressure.c: fix a signedness bug in vmpressure_register_event()
	firmware: google: increment VPD key_len properly
	gpiolib: don't clear FLAG_IS_OUT when emulating open-drain/open-source
	iio: adc: stm32-adc: move registers definitions
	iio: adc: stm32-adc: fix a race when using several adcs with dma and irq
	cifs: use cifsInodeInfo->open_file_lock while iterating to avoid a panic
	btrfs: fix incorrect updating of log root tree
	btrfs: fix uninitialized ret in ref-verify
	NFS: Fix O_DIRECT accounting of number of bytes read/written
	MIPS: Disable Loongson MMI instructions for kernel build
	MIPS: elf_hwcap: Export userspace ASEs
	ACPICA: ACPI 6.3: PPTT add additional fields in Processor Structure Flags
	ACPI/PPTT: Add support for ACPI 6.3 thread flag
	arm64: topology: Use PPTT to determine if PE is a thread
	Fix the locking in dcache_readdir() and friends
	media: stkwebcam: fix runtime PM after driver unbind
	arm64/sve: Fix wrong free for task->thread.sve_state
	tracing/hwlat: Report total time spent in all NMIs during the sample
	tracing/hwlat: Don't ignore outer-loop duration when calculating max_latency
	ftrace: Get a reference counter for the trace_array on filter files
	tracing: Get trace_array reference for available_tracers files
	hwmon: Fix HWMON_P_MIN_ALARM mask
	x86/asm: Fix MWAITX C-state hint value
	PCI: vmd: Fix config addressing when using bus offsets
	perf/hw_breakpoint: Fix arch_hw_breakpoint use-before-initialization
	Linux 4.19.80

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I7b092168ec736afa21e2886261dfb1d5690129b4
This commit is contained in:
Greg Kroah-Hartman 2019-10-17 15:33:53 -07:00
commit fd673e8f7f
92 changed files with 967 additions and 1252 deletions

View file

@ -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

View file

@ -15117,13 +15117,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

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 19
SUBLEVEL = 79
SUBLEVEL = 80
EXTRAVERSION =
NAME = "People's Front"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -285,22 +285,27 @@ void arch_release_task_struct(struct task_struct *tsk)
fpsimd_release_task(tsk);
}
/*
* src and dst may temporarily have aliased sve_state after task_struct
* is copied. We cannot fix this properly here, because src may have
* live SVE state and dst's thread_info may not exist yet, so tweaking
* either src's or dst's TIF_SVE is not safe.
*
* The unaliasing is done in copy_thread() instead. This works because
* dst is not schedulable or traceable until both of these functions
* have been called.
*/
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
if (current->mm)
fpsimd_preserve_current_state();
*dst = *src;
/* We rely on the above assignment to initialize dst's thread_flags: */
BUILD_BUG_ON(!IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK));
/*
* Detach src's sve_state (if any) from dst so that it does not
* get erroneously used or freed prematurely. dst's sve_state
* will be allocated on demand later on if dst uses SVE.
* For consistency, also clear TIF_SVE here: this could be done
* later in copy_process(), but to avoid tripping up future
* maintainers it is best not to leave TIF_SVE and sve_state in
* an inconsistent state, even temporarily.
*/
dst->thread.sve_state = NULL;
clear_tsk_thread_flag(dst, TIF_SVE);
return 0;
}
@ -313,13 +318,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
/*
* Unalias p->thread.sve_state (if any) from the parent task
* and disable discard SVE state for p:
*/
clear_tsk_thread_flag(p, TIF_SVE);
p->thread.sve_state = NULL;
/*
* In case p was allocated the same task_struct pointer as some
* other recently-exited task, make sure p is disassociated from

View file

@ -340,17 +340,28 @@ void remove_cpu_topology(unsigned int cpu)
}
#ifdef CONFIG_ACPI
static bool __init acpi_cpu_is_threaded(int cpu)
{
int is_threaded = acpi_pptt_cpu_is_thread(cpu);
/*
* if the PPTT doesn't have thread information, assume a homogeneous
* machine and return the current CPU's thread state.
*/
if (is_threaded < 0)
is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
return !!is_threaded;
}
/*
* Propagate the topology information of the processor_topology_node tree to the
* cpu_topology array.
*/
static int __init parse_acpi_topology(void)
{
bool is_threaded;
int cpu, topology_id;
is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
for_each_possible_cpu(cpu) {
int i, cache_id;
@ -358,7 +369,7 @@ static int __init parse_acpi_topology(void)
if (topology_id < 0)
return topology_id;
if (is_threaded) {
if (acpi_cpu_is_threaded(cpu)) {
cpu_topology[cpu].thread_id = topology_id;
topology_id = find_acpi_cpu_topology(cpu, 1);
cpu_topology[cpu].core_id = topology_id;

View file

@ -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

View file

@ -335,7 +335,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

View file

@ -6,5 +6,16 @@
#define HWCAP_MIPS_R6 (1 << 0)
#define HWCAP_MIPS_MSA (1 << 1)
#define HWCAP_MIPS_CRC32 (1 << 2)
#define HWCAP_MIPS_MIPS16 (1 << 3)
#define HWCAP_MIPS_MDMX (1 << 4)
#define HWCAP_MIPS_MIPS3D (1 << 5)
#define HWCAP_MIPS_SMARTMIPS (1 << 6)
#define HWCAP_MIPS_DSP (1 << 7)
#define HWCAP_MIPS_DSP2 (1 << 8)
#define HWCAP_MIPS_DSP3 (1 << 9)
#define HWCAP_MIPS_MIPS16E2 (1 << 10)
#define HWCAP_LOONGSON_MMI (1 << 11)
#define HWCAP_LOONGSON_EXT (1 << 12)
#define HWCAP_LOONGSON_EXT2 (1 << 13)
#endif /* _UAPI_ASM_HWCAP_H */

View file

@ -2105,6 +2105,39 @@ void cpu_probe(void)
elf_hwcap |= HWCAP_MIPS_MSA;
}
if (cpu_has_mips16)
elf_hwcap |= HWCAP_MIPS_MIPS16;
if (cpu_has_mdmx)
elf_hwcap |= HWCAP_MIPS_MDMX;
if (cpu_has_mips3d)
elf_hwcap |= HWCAP_MIPS_MIPS3D;
if (cpu_has_smartmips)
elf_hwcap |= HWCAP_MIPS_SMARTMIPS;
if (cpu_has_dsp)
elf_hwcap |= HWCAP_MIPS_DSP;
if (cpu_has_dsp2)
elf_hwcap |= HWCAP_MIPS_DSP2;
if (cpu_has_dsp3)
elf_hwcap |= HWCAP_MIPS_DSP3;
if (cpu_has_mips16e2)
elf_hwcap |= HWCAP_MIPS_MIPS16E2;
if (cpu_has_loongson_mmi)
elf_hwcap |= HWCAP_LOONGSON_MMI;
if (cpu_has_loongson_ext)
elf_hwcap |= HWCAP_LOONGSON_EXT;
if (cpu_has_loongson_ext2)
elf_hwcap |= HWCAP_LOONGSON_EXT2;
if (cpu_has_vz)
cpu_probe_vz(c);

View file

@ -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
#

View file

@ -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__
ifeq ($(cc-name),clang)

View file

@ -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)

View file

@ -113,8 +113,8 @@ static void delay_mwaitx(unsigned long __loops)
__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);

View file

@ -148,24 +148,27 @@ bool rq_depth_calc_max_depth(struct rq_depth *rqd)
return ret;
}
void rq_depth_scale_up(struct rq_depth *rqd)
/* Returns true on success and false if scaling up wasn't possible */
bool rq_depth_scale_up(struct rq_depth *rqd)
{
/*
* Hit max in previous round, stop here
*/
if (rqd->scaled_max)
return;
return false;
rqd->scale_step--;
rqd->scaled_max = rq_depth_calc_max_depth(rqd);
return true;
}
/*
* Scale rwb down. If 'hard_throttle' is set, do it quicker, since we
* had a latency violation.
* had a latency violation. Returns true on success and returns false if
* scaling down wasn't possible.
*/
void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
bool rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
{
/*
* Stop scaling down when we've hit the limit. This also prevents
@ -173,7 +176,7 @@ void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
* keep up.
*/
if (rqd->max_depth == 1)
return;
return false;
if (rqd->scale_step < 0 && hard_throttle)
rqd->scale_step = 0;
@ -182,6 +185,7 @@ void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
rqd->scaled_max = false;
rq_depth_calc_max_depth(rqd);
return true;
}
void rq_qos_exit(struct request_queue *q)

View file

@ -94,8 +94,8 @@ static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
}
bool rq_wait_inc_below(struct rq_wait *rq_wait, unsigned int limit);
void rq_depth_scale_up(struct rq_depth *rqd);
void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle);
bool rq_depth_scale_up(struct rq_depth *rqd);
bool rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle);
bool rq_depth_calc_max_depth(struct rq_depth *rqd);
void rq_qos_cleanup(struct request_queue *, struct bio *);

View file

@ -307,7 +307,8 @@ static void calc_wb_limits(struct rq_wb *rwb)
static void scale_up(struct rq_wb *rwb)
{
rq_depth_scale_up(&rwb->rq_depth);
if (!rq_depth_scale_up(&rwb->rq_depth))
return;
calc_wb_limits(rwb);
rwb->unknown_cnt = 0;
rwb_wake_all(rwb);
@ -316,7 +317,8 @@ static void scale_up(struct rq_wb *rwb)
static void scale_down(struct rq_wb *rwb, bool hard_throttle)
{
rq_depth_scale_down(&rwb->rq_depth, hard_throttle);
if (!rq_depth_scale_down(&rwb->rq_depth, hard_throttle))
return;
calc_wb_limits(rwb);
rwb->unknown_cnt = 0;
rwb_trace_step(rwb, "scale down");

View file

@ -509,6 +509,44 @@ static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag)
return retval;
}
/**
* check_acpi_cpu_flag() - Determine if CPU node has a flag set
* @cpu: Kernel logical CPU number
* @rev: The minimum PPTT revision defining the flag
* @flag: The flag itself
*
* Check the node representing a CPU for a given flag.
*
* Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found or
* the table revision isn't new enough.
* 1, any passed flag set
* 0, flag unset
*/
static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag)
{
struct acpi_table_header *table;
acpi_status status;
u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
struct acpi_pptt_processor *cpu_node = NULL;
int ret = -ENOENT;
status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
if (ACPI_FAILURE(status)) {
pr_warn_once("No PPTT table found, cpu topology may be inaccurate\n");
return ret;
}
if (table->revision >= rev)
cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
if (cpu_node)
ret = (cpu_node->flags & flag) != 0;
acpi_put_table(table);
return ret;
}
/**
* acpi_find_last_cache_level() - Determines the number of cache levels for a PE
* @cpu: Kernel logical cpu number
@ -573,6 +611,20 @@ int cache_setup_acpi(unsigned int cpu)
return status;
}
/**
* acpi_pptt_cpu_is_thread() - Determine if CPU is a thread
* @cpu: Kernel logical CPU number
*
* Return: 1, a thread
* 0, not a thread
* -ENOENT ,if the PPTT doesn't exist, the CPU cannot be found or
* the table revision isn't new enough.
*/
int acpi_pptt_cpu_is_thread(unsigned int cpu)
{
return check_acpi_cpu_flag(cpu, 2, ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD);
}
/**
* find_acpi_cpu_topology() - Determine a unique topology value for a given cpu
* @cpu: Kernel logical cpu number

View file

@ -281,6 +281,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) {

View file

@ -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;
}

View file

@ -529,11 +529,12 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip)
}
for_each_set_bit(n, &reg, SPRD_EIC_PER_BANK_NR) {
girq = irq_find_mapping(chip->irq.domain,
bank * SPRD_EIC_PER_BANK_NR + n);
u32 offset = bank * SPRD_EIC_PER_BANK_NR + n;
girq = irq_find_mapping(chip->irq.domain, offset);
generic_handle_irq(girq);
sprd_eic_toggle_trigger(chip, girq, n);
sprd_eic_toggle_trigger(chip, girq, offset);
}
}
}

View file

@ -2649,8 +2649,10 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
if (!ret)
goto set_output_value;
/* Emulate open drain by not actively driving the line high */
if (value)
return gpiod_direction_input(desc);
if (value) {
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),
@ -2658,8 +2660,10 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
if (!ret)
goto set_output_value;
/* Emulate open source by not actively driving the line low */
if (!value)
return gpiod_direction_input(desc);
if (!value) {
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);
@ -2667,6 +2671,17 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
set_output_value:
return gpiod_direction_output_raw_commit(desc, value);
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;
}
EXPORT_SYMBOL_GPL(gpiod_direction_output);
@ -2980,8 +2995,6 @@ static void gpio_set_open_drain_value_commit(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)
@ -3011,8 +3024,6 @@ static void gpio_set_open_source_value_commit(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)

View file

@ -814,10 +814,10 @@ static int ad799x_probe(struct i2c_client *client,
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,

View file

@ -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)
@ -186,10 +192,36 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
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.

View file

@ -109,14 +109,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);
/*
@ -126,7 +126,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
@ -134,7 +133,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
@ -142,7 +141,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)

View file

@ -21,45 +21,22 @@
#include "stm32-adc-core.h"
/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
/* STM32F4_ADC_CSR - bit fields */
#define STM32F4_EOC3 BIT(17)
#define STM32F4_EOC2 BIT(9)
#define STM32F4_EOC1 BIT(1)
/* STM32F4_ADC_CCR - bit fields */
#define STM32F4_ADC_ADCPRE_SHIFT 16
#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
/* STM32H7_ADC_CSR - bit fields */
#define STM32H7_EOC_SLV BIT(18)
#define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */
#define STM32H7_PRESC_SHIFT 18
#define STM32H7_PRESC_MASK GENMASK(21, 18)
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
/**
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
* @csr: common status register offset
* @eoc1: adc1 end of conversion flag in @csr
* @eoc2: adc2 end of conversion flag in @csr
* @eoc3: adc3 end of conversion flag in @csr
* @ier: interrupt enable register offset for each adc
* @eocie_msk: end of conversion interrupt enable mask in @ier
*/
struct stm32_adc_common_regs {
u32 csr;
u32 eoc1_msk;
u32 eoc2_msk;
u32 eoc3_msk;
u32 ier;
u32 eocie_msk;
};
struct stm32_adc_priv;
@ -268,6 +245,8 @@ static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
.eoc1_msk = STM32F4_EOC1,
.eoc2_msk = STM32F4_EOC2,
.eoc3_msk = STM32F4_EOC3,
.ier = STM32F4_ADC_CR1,
.eocie_msk = STM32F4_EOCIE,
};
/* STM32H7 common registers definitions */
@ -275,8 +254,24 @@ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
.csr = STM32H7_ADC_CSR,
.eoc1_msk = STM32H7_EOC_MST,
.eoc2_msk = STM32H7_EOC_SLV,
.ier = STM32H7_ADC_IER,
.eocie_msk = STM32H7_EOCIE,
};
static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2,
};
static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv,
unsigned int adc)
{
u32 ier, offset = stm32_adc_offset[adc];
ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier);
return ier & priv->cfg->regs->eocie_msk;
}
/* ADC common interrupt for all instances */
static void stm32_adc_irq_handler(struct irq_desc *desc)
{
@ -287,13 +282,28 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
chained_irq_enter(chip, desc);
status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
if (status & priv->cfg->regs->eoc1_msk)
/*
* End of conversion may be handled by using IRQ or DMA. There may be a
* race here when two conversions complete at the same time on several
* ADCs. EOC may be read 'set' for several ADCs, with:
* - an ADC configured to use DMA (EOC triggers the DMA request, and
* is then automatically cleared by DR read in hardware)
* - an ADC configured to use IRQs (EOCIE bit is set. The handler must
* be called in this case)
* So both EOC status bit in CSR and EOCIE control bit must be checked
* before invoking the interrupt handler (e.g. call ISR only for
* IRQ-enabled ADCs).
*/
if (status & priv->cfg->regs->eoc1_msk &&
stm32_adc_eoc_enabled(priv, 0))
generic_handle_irq(irq_find_mapping(priv->domain, 0));
if (status & priv->cfg->regs->eoc2_msk)
if (status & priv->cfg->regs->eoc2_msk &&
stm32_adc_eoc_enabled(priv, 1))
generic_handle_irq(irq_find_mapping(priv->domain, 1));
if (status & priv->cfg->regs->eoc3_msk)
if (status & priv->cfg->regs->eoc3_msk &&
stm32_adc_eoc_enabled(priv, 2))
generic_handle_irq(irq_find_mapping(priv->domain, 2));
chained_irq_exit(chip, desc);

View file

@ -25,8 +25,145 @@
* --------------------------------------------------------
*/
#define STM32_ADC_MAX_ADCS 3
#define STM32_ADC_OFFSET 0x100
#define STM32_ADCX_COMN_OFFSET 0x300
/* STM32F4 - Registers for each ADC instance */
#define STM32F4_ADC_SR 0x00
#define STM32F4_ADC_CR1 0x04
#define STM32F4_ADC_CR2 0x08
#define STM32F4_ADC_SMPR1 0x0C
#define STM32F4_ADC_SMPR2 0x10
#define STM32F4_ADC_HTR 0x24
#define STM32F4_ADC_LTR 0x28
#define STM32F4_ADC_SQR1 0x2C
#define STM32F4_ADC_SQR2 0x30
#define STM32F4_ADC_SQR3 0x34
#define STM32F4_ADC_JSQR 0x38
#define STM32F4_ADC_JDR1 0x3C
#define STM32F4_ADC_JDR2 0x40
#define STM32F4_ADC_JDR3 0x44
#define STM32F4_ADC_JDR4 0x48
#define STM32F4_ADC_DR 0x4C
/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
/* STM32F4_ADC_SR - bit fields */
#define STM32F4_STRT BIT(4)
#define STM32F4_EOC BIT(1)
/* STM32F4_ADC_CR1 - bit fields */
#define STM32F4_RES_SHIFT 24
#define STM32F4_RES_MASK GENMASK(25, 24)
#define STM32F4_SCAN BIT(8)
#define STM32F4_EOCIE BIT(5)
/* STM32F4_ADC_CR2 - bit fields */
#define STM32F4_SWSTART BIT(30)
#define STM32F4_EXTEN_SHIFT 28
#define STM32F4_EXTEN_MASK GENMASK(29, 28)
#define STM32F4_EXTSEL_SHIFT 24
#define STM32F4_EXTSEL_MASK GENMASK(27, 24)
#define STM32F4_EOCS BIT(10)
#define STM32F4_DDS BIT(9)
#define STM32F4_DMA BIT(8)
#define STM32F4_ADON BIT(0)
/* STM32F4_ADC_CSR - bit fields */
#define STM32F4_EOC3 BIT(17)
#define STM32F4_EOC2 BIT(9)
#define STM32F4_EOC1 BIT(1)
/* STM32F4_ADC_CCR - bit fields */
#define STM32F4_ADC_ADCPRE_SHIFT 16
#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
/* STM32H7 - Registers for each ADC instance */
#define STM32H7_ADC_ISR 0x00
#define STM32H7_ADC_IER 0x04
#define STM32H7_ADC_CR 0x08
#define STM32H7_ADC_CFGR 0x0C
#define STM32H7_ADC_SMPR1 0x14
#define STM32H7_ADC_SMPR2 0x18
#define STM32H7_ADC_PCSEL 0x1C
#define STM32H7_ADC_SQR1 0x30
#define STM32H7_ADC_SQR2 0x34
#define STM32H7_ADC_SQR3 0x38
#define STM32H7_ADC_SQR4 0x3C
#define STM32H7_ADC_DR 0x40
#define STM32H7_ADC_DIFSEL 0xC0
#define STM32H7_ADC_CALFACT 0xC4
#define STM32H7_ADC_CALFACT2 0xC8
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
/* STM32H7_ADC_ISR - bit fields */
#define STM32MP1_VREGREADY BIT(12)
#define STM32H7_EOC BIT(2)
#define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_IER - bit fields */
#define STM32H7_EOCIE STM32H7_EOC
/* STM32H7_ADC_CR - bit fields */
#define STM32H7_ADCAL BIT(31)
#define STM32H7_ADCALDIF BIT(30)
#define STM32H7_DEEPPWD BIT(29)
#define STM32H7_ADVREGEN BIT(28)
#define STM32H7_LINCALRDYW6 BIT(27)
#define STM32H7_LINCALRDYW5 BIT(26)
#define STM32H7_LINCALRDYW4 BIT(25)
#define STM32H7_LINCALRDYW3 BIT(24)
#define STM32H7_LINCALRDYW2 BIT(23)
#define STM32H7_LINCALRDYW1 BIT(22)
#define STM32H7_ADCALLIN BIT(16)
#define STM32H7_BOOST BIT(8)
#define STM32H7_ADSTP BIT(4)
#define STM32H7_ADSTART BIT(2)
#define STM32H7_ADDIS BIT(1)
#define STM32H7_ADEN BIT(0)
/* STM32H7_ADC_CFGR bit fields */
#define STM32H7_EXTEN_SHIFT 10
#define STM32H7_EXTEN_MASK GENMASK(11, 10)
#define STM32H7_EXTSEL_SHIFT 5
#define STM32H7_EXTSEL_MASK GENMASK(9, 5)
#define STM32H7_RES_SHIFT 2
#define STM32H7_RES_MASK GENMASK(4, 2)
#define STM32H7_DMNGT_SHIFT 0
#define STM32H7_DMNGT_MASK GENMASK(1, 0)
enum stm32h7_adc_dmngt {
STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */
STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */
STM32H7_DMNGT_DFSDM, /* DFSDM mode */
STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */
};
/* STM32H7_ADC_CALFACT - bit fields */
#define STM32H7_CALFACT_D_SHIFT 16
#define STM32H7_CALFACT_D_MASK GENMASK(26, 16)
#define STM32H7_CALFACT_S_SHIFT 0
#define STM32H7_CALFACT_S_MASK GENMASK(10, 0)
/* STM32H7_ADC_CALFACT2 - bit fields */
#define STM32H7_LINCALFACT_SHIFT 0
#define STM32H7_LINCALFACT_MASK GENMASK(29, 0)
/* STM32H7_ADC_CSR - bit fields */
#define STM32H7_EOC_SLV BIT(18)
#define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */
#define STM32H7_PRESC_SHIFT 18
#define STM32H7_PRESC_MASK GENMASK(21, 18)
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
/**
* struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr

View file

@ -27,115 +27,6 @@
#include "stm32-adc-core.h"
/* STM32F4 - Registers for each ADC instance */
#define STM32F4_ADC_SR 0x00
#define STM32F4_ADC_CR1 0x04
#define STM32F4_ADC_CR2 0x08
#define STM32F4_ADC_SMPR1 0x0C
#define STM32F4_ADC_SMPR2 0x10
#define STM32F4_ADC_HTR 0x24
#define STM32F4_ADC_LTR 0x28
#define STM32F4_ADC_SQR1 0x2C
#define STM32F4_ADC_SQR2 0x30
#define STM32F4_ADC_SQR3 0x34
#define STM32F4_ADC_JSQR 0x38
#define STM32F4_ADC_JDR1 0x3C
#define STM32F4_ADC_JDR2 0x40
#define STM32F4_ADC_JDR3 0x44
#define STM32F4_ADC_JDR4 0x48
#define STM32F4_ADC_DR 0x4C
/* STM32F4_ADC_SR - bit fields */
#define STM32F4_STRT BIT(4)
#define STM32F4_EOC BIT(1)
/* STM32F4_ADC_CR1 - bit fields */
#define STM32F4_RES_SHIFT 24
#define STM32F4_RES_MASK GENMASK(25, 24)
#define STM32F4_SCAN BIT(8)
#define STM32F4_EOCIE BIT(5)
/* STM32F4_ADC_CR2 - bit fields */
#define STM32F4_SWSTART BIT(30)
#define STM32F4_EXTEN_SHIFT 28
#define STM32F4_EXTEN_MASK GENMASK(29, 28)
#define STM32F4_EXTSEL_SHIFT 24
#define STM32F4_EXTSEL_MASK GENMASK(27, 24)
#define STM32F4_EOCS BIT(10)
#define STM32F4_DDS BIT(9)
#define STM32F4_DMA BIT(8)
#define STM32F4_ADON BIT(0)
/* STM32H7 - Registers for each ADC instance */
#define STM32H7_ADC_ISR 0x00
#define STM32H7_ADC_IER 0x04
#define STM32H7_ADC_CR 0x08
#define STM32H7_ADC_CFGR 0x0C
#define STM32H7_ADC_SMPR1 0x14
#define STM32H7_ADC_SMPR2 0x18
#define STM32H7_ADC_PCSEL 0x1C
#define STM32H7_ADC_SQR1 0x30
#define STM32H7_ADC_SQR2 0x34
#define STM32H7_ADC_SQR3 0x38
#define STM32H7_ADC_SQR4 0x3C
#define STM32H7_ADC_DR 0x40
#define STM32H7_ADC_DIFSEL 0xC0
#define STM32H7_ADC_CALFACT 0xC4
#define STM32H7_ADC_CALFACT2 0xC8
/* STM32H7_ADC_ISR - bit fields */
#define STM32MP1_VREGREADY BIT(12)
#define STM32H7_EOC BIT(2)
#define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_IER - bit fields */
#define STM32H7_EOCIE STM32H7_EOC
/* STM32H7_ADC_CR - bit fields */
#define STM32H7_ADCAL BIT(31)
#define STM32H7_ADCALDIF BIT(30)
#define STM32H7_DEEPPWD BIT(29)
#define STM32H7_ADVREGEN BIT(28)
#define STM32H7_LINCALRDYW6 BIT(27)
#define STM32H7_LINCALRDYW5 BIT(26)
#define STM32H7_LINCALRDYW4 BIT(25)
#define STM32H7_LINCALRDYW3 BIT(24)
#define STM32H7_LINCALRDYW2 BIT(23)
#define STM32H7_LINCALRDYW1 BIT(22)
#define STM32H7_ADCALLIN BIT(16)
#define STM32H7_BOOST BIT(8)
#define STM32H7_ADSTP BIT(4)
#define STM32H7_ADSTART BIT(2)
#define STM32H7_ADDIS BIT(1)
#define STM32H7_ADEN BIT(0)
/* STM32H7_ADC_CFGR bit fields */
#define STM32H7_EXTEN_SHIFT 10
#define STM32H7_EXTEN_MASK GENMASK(11, 10)
#define STM32H7_EXTSEL_SHIFT 5
#define STM32H7_EXTSEL_MASK GENMASK(9, 5)
#define STM32H7_RES_SHIFT 2
#define STM32H7_RES_MASK GENMASK(4, 2)
#define STM32H7_DMNGT_SHIFT 0
#define STM32H7_DMNGT_MASK GENMASK(1, 0)
enum stm32h7_adc_dmngt {
STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */
STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */
STM32H7_DMNGT_DFSDM, /* DFSDM mode */
STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */
};
/* STM32H7_ADC_CALFACT - bit fields */
#define STM32H7_CALFACT_D_SHIFT 16
#define STM32H7_CALFACT_D_MASK GENMASK(26, 16)
#define STM32H7_CALFACT_S_SHIFT 0
#define STM32H7_CALFACT_S_MASK GENMASK(10, 0)
/* STM32H7_ADC_CALFACT2 - bit fields */
#define STM32H7_LINCALFACT_SHIFT 0
#define STM32H7_LINCALFACT_MASK GENMASK(29, 0)
/* Number of linear calibration shadow registers / LINCALRDYW control bits */
#define STM32H7_LINCALFACT_NUM 6

View file

@ -694,6 +694,7 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
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);
@ -728,13 +729,16 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
}
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;
}

View file

@ -641,7 +641,6 @@ static int v4l_stk_release(struct file *fp)
dev->owner = NULL;
}
if (is_present(dev))
usb_autopm_put_interface(dev->interface);
mutex_unlock(&dev->lock);
return v4l2_fh_release(fp);

View file

@ -214,13 +214,21 @@ static void mei_mkhi_fix(struct mei_cl_device *cldev)
{
int ret;
/* No need to enable the client if nothing is needed from it */
if (!cldev->bus->fw_f_fw_ver_supported &&
!cldev->bus->hbm_f_os_supported)
return;
ret = mei_cldev_enable(cldev);
if (ret)
return;
if (cldev->bus->fw_f_fw_ver_supported) {
ret = mei_fwver(cldev);
if (ret < 0)
dev_err(&cldev->dev, "FW version command failed %d\n", ret);
dev_err(&cldev->dev, "FW version command failed %d\n",
ret);
}
if (cldev->bus->hbm_f_os_supported) {
ret = mei_osver(cldev);

View file

@ -139,6 +139,9 @@
#define MEI_DEV_ID_CNP_H 0xA360 /* Cannon Point H */
#define MEI_DEV_ID_CNP_H_4 0xA364 /* Cannon Point H 4 (iTouch) */
#define MEI_DEV_ID_CMP_LP 0x02e0 /* Comet Point LP */
#define MEI_DEV_ID_CMP_LP_3 0x02e4 /* Comet Point LP 3 (iTouch) */
#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
#define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */

View file

@ -1368,6 +1368,8 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
#define MEI_CFG_FW_SPS \
.quirk_probe = mei_me_fw_type_sps
#define MEI_CFG_FW_VER_SUPP \
.fw_ver_supported = 1
#define MEI_CFG_ICH_HFS \
.fw_status.count = 0
@ -1405,31 +1407,41 @@ static const struct mei_cfg mei_me_ich10_cfg = {
MEI_CFG_ICH10_HFS,
};
/* PCH devices */
static const struct mei_cfg mei_me_pch_cfg = {
/* PCH6 devices */
static const struct mei_cfg mei_me_pch6_cfg = {
MEI_CFG_PCH_HFS,
};
/* PCH7 devices */
static const struct mei_cfg mei_me_pch7_cfg = {
MEI_CFG_PCH_HFS,
MEI_CFG_FW_VER_SUPP,
};
/* PCH Cougar Point and Patsburg with quirk for Node Manager exclusion */
static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = {
MEI_CFG_PCH_HFS,
MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_NM,
};
/* PCH8 Lynx Point and newer devices */
static const struct mei_cfg mei_me_pch8_cfg = {
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
};
/* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
static const struct mei_cfg mei_me_pch8_sps_cfg = {
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_SPS,
};
/* Cannon Lake and newer devices */
static const struct mei_cfg mei_me_pch12_cfg = {
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
MEI_CFG_DMA_128,
};
@ -1441,7 +1453,8 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_UNDEF_CFG] = NULL,
[MEI_ME_ICH_CFG] = &mei_me_ich_cfg,
[MEI_ME_ICH10_CFG] = &mei_me_ich10_cfg,
[MEI_ME_PCH_CFG] = &mei_me_pch_cfg,
[MEI_ME_PCH6_CFG] = &mei_me_pch6_cfg,
[MEI_ME_PCH7_CFG] = &mei_me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = &mei_me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = &mei_me_pch8_cfg,
[MEI_ME_PCH8_SPS_CFG] = &mei_me_pch8_sps_cfg,
@ -1480,6 +1493,8 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
mei_device_init(dev, &pdev->dev, &mei_me_hw_ops);
hw->cfg = cfg;
dev->fw_f_fw_ver_supported = cfg->fw_ver_supported;
return dev;
}

View file

@ -32,11 +32,13 @@
* @fw_status: FW status
* @quirk_probe: device exclusion quirk
* @dma_size: device DMA buffers size
* @fw_ver_supported: is fw version retrievable from FW
*/
struct mei_cfg {
const struct mei_fw_status fw_status;
bool (*quirk_probe)(struct pci_dev *pdev);
size_t dma_size[DMA_DSCR_NUM];
u32 fw_ver_supported:1;
};
@ -74,7 +76,8 @@ struct mei_me_hw {
* @MEI_ME_UNDEF_CFG: Lower sentinel.
* @MEI_ME_ICH_CFG: I/O Controller Hub legacy devices.
* @MEI_ME_ICH10_CFG: I/O Controller Hub platforms Gen10
* @MEI_ME_PCH_CFG: Platform Controller Hub platforms (Up to Gen8).
* @MEI_ME_PCH6_CFG: Platform Controller Hub platforms (Gen6).
* @MEI_ME_PCH7_CFG: Platform Controller Hub platforms (Gen7).
* @MEI_ME_PCH_CPT_PBG_CFG:Platform Controller Hub workstations
* with quirk for Node Manager exclusion.
* @MEI_ME_PCH8_CFG: Platform Controller Hub Gen8 and newer
@ -89,7 +92,8 @@ enum mei_cfg_idx {
MEI_ME_UNDEF_CFG,
MEI_ME_ICH_CFG,
MEI_ME_ICH10_CFG,
MEI_ME_PCH_CFG,
MEI_ME_PCH6_CFG,
MEI_ME_PCH7_CFG,
MEI_ME_PCH_CPT_PBG_CFG,
MEI_ME_PCH8_CFG,
MEI_ME_PCH8_SPS_CFG,

View file

@ -422,6 +422,8 @@ struct mei_fw_version {
*
* @fw_ver : FW versions
*
* @fw_f_fw_ver_supported : fw feature: fw version supported
*
* @me_clients_rwsem: rw lock over me_clients list
* @me_clients : list of FW clients
* @me_clients_map : FW clients bit map
@ -500,6 +502,8 @@ struct mei_device {
struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS];
unsigned int fw_f_fw_ver_supported:1;
struct rw_semaphore me_clients_rwsem;
struct list_head me_clients;
DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);

View file

@ -70,13 +70,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_3, MEI_ME_ICH10_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_4, MEI_ME_ICH10_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, MEI_ME_PCH_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, MEI_ME_PCH_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, MEI_ME_PCH6_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, MEI_ME_PCH6_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CPT_1, MEI_ME_PCH_CPT_PBG_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PBG_1, MEI_ME_PCH_CPT_PBG_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, MEI_ME_PCH_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, MEI_ME_PCH_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, MEI_ME_PCH_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, MEI_ME_PCH7_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, MEI_ME_PCH7_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, MEI_ME_PCH7_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, MEI_ME_PCH8_SPS_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, MEI_ME_PCH8_SPS_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, MEI_ME_PCH8_CFG)},
@ -105,6 +105,9 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},

View file

@ -97,6 +97,7 @@ struct vmd_dev {
struct resource resources[3];
struct irq_domain *irq_domain;
struct pci_bus *bus;
u8 busn_start;
#ifdef CONFIG_X86_DEV_DMA_OPS
struct dma_map_ops dma_ops;
@ -468,7 +469,8 @@ static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,
unsigned int devfn, int reg, int len)
{
char __iomem *addr = vmd->cfgbar +
(bus->number << 20) + (devfn << 12) + reg;
((bus->number - vmd->busn_start) << 20) +
(devfn << 12) + reg;
if ((addr - vmd->cfgbar) + len >=
resource_size(&vmd->dev->resource[VMD_CFGBAR]))
@ -591,7 +593,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
unsigned long flags;
LIST_HEAD(resources);
resource_size_t offset[2] = {0};
resource_size_t membar2_offset = 0x2000, busn_start = 0;
resource_size_t membar2_offset = 0x2000;
/*
* Shadow registers may exist in certain VMD device ids which allow
@ -633,14 +635,14 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
pci_read_config_dword(vmd->dev, PCI_REG_VMCONFIG, &vmconfig);
if (BUS_RESTRICT_CAP(vmcap) &&
(BUS_RESTRICT_CFG(vmconfig) == 0x1))
busn_start = 128;
vmd->busn_start = 128;
}
res = &vmd->dev->resource[VMD_CFGBAR];
vmd->resources[0] = (struct resource) {
.name = "VMD CFGBAR",
.start = busn_start,
.end = busn_start + (resource_size(res) >> 20) - 1,
.start = vmd->busn_start,
.end = vmd->busn_start + (resource_size(res) >> 20) - 1,
.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
};
@ -708,8 +710,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
vmd->bus = pci_create_root_bus(&vmd->dev->dev, busn_start, &vmd_ops,
sd, &resources);
vmd->bus = pci_create_root_bus(&vmd->dev->dev, vmd->busn_start,
&vmd_ops, sd, &resources);
if (!vmd->bus) {
pci_free_resource_list(&resources);
irq_domain_remove(vmd->irq_domain);

View file

@ -819,7 +819,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 */
@ -836,7 +836,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;
}
@ -872,6 +872,9 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
return info;
release_framebuf:
framebuffer_release(info);
alloc_fail:
vfree(vmem);

View file

@ -1755,8 +1755,10 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
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);

View file

@ -837,6 +837,7 @@ static int __init ulite_init(void)
static void __exit ulite_exit(void)
{
platform_driver_unregister(&ulite_platform_driver);
if (ulite_uart_driver.state)
uart_unregister_driver(&ulite_uart_driver);
}

View file

@ -461,10 +461,12 @@ static int usblp_release(struct inode *inode, struct file *file)
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 */
if (!usblp->present) /* finish cleanup from disconnect */
usblp_cleanup(usblp);
mutex_unlock(&usblp_mutex);
return 0;

View file

@ -48,6 +48,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";
@ -2446,7 +2447,7 @@ static int dummy_start_ss(struct dummy_hcd *dum_hcd)
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

View file

@ -3154,10 +3154,10 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
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 {

View file

@ -1022,7 +1022,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
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
@ -1098,6 +1098,18 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
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 */
@ -3053,6 +3065,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
unsigned int ep_index;
unsigned long flags;
u32 ep_flag;
int err;
xhci = hcd_to_xhci(hcd);
if (!host_ep->hcpriv)
@ -3102,7 +3115,17 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
xhci_free_command(xhci, cfg_cmd);
goto cleanup;
}
xhci_queue_stop_endpoint(xhci, stop_cmd, udev->slot_id, ep_index, 0);
err = xhci_queue_stop_endpoint(xhci, stop_cmd, udev->slot_id,
ep_index, 0);
if (err < 0) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_free_command(xhci, cfg_cmd);
xhci_dbg(xhci, "%s: Failed to queue stop ep command, %d ",
__func__, err);
goto cleanup;
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
@ -3116,8 +3139,16 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
ctrl_ctx, ep_flag, ep_flag);
xhci_endpoint_copy(xhci, cfg_cmd->in_ctx, vdev->out_ctx, ep_index);
xhci_queue_configure_endpoint(xhci, cfg_cmd, cfg_cmd->in_ctx->dma,
err = xhci_queue_configure_endpoint(xhci, cfg_cmd, cfg_cmd->in_ctx->dma,
udev->slot_id, false);
if (err < 0) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_free_command(xhci, cfg_cmd);
xhci_dbg(xhci, "%s: Failed to queue config ep command, %d ",
__func__, err);
goto cleanup;
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
@ -4631,12 +4662,12 @@ static int xhci_update_timeout_for_endpoint(struct xhci_hcd *xhci,
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;
}
@ -4747,10 +4778,12 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd,
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",
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);
timeout = xhci_get_timeout_no_hub_lpm(udev,
state);
if (timeout == USB3_LPM_DISABLED)
return timeout;
}
}
@ -5034,10 +5067,17 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
hcd->has_tt = 1;
} else {
/*
* Some 3.1 hosts return sbrn 0x30, use xhci supported protocol
* minor revision instead of sbrn. Minor revision is a two digit
* BCD containing minor and sub-minor numbers, only show minor.
* Early xHCI 1.1 spec did not mention USB 3.1 capable hosts
* should return 0x31 for sbrn, or that the minor revision
* is a two digit BCD containig minor and sub-minor numbers.
* This was later clarified in xHCI 1.2.
*
* Some USB 3.1 capable hosts therefore have sbrn 0x30, and
* minor revision set to 0x1 instead of 0x10.
*/
if (xhci->usb3_rhub.min_rev == 0x1)
minor_rev = 1;
else
minor_rev = xhci->usb3_rhub.min_rev / 0x10;
switch (minor_rev) {

View file

@ -721,6 +721,10 @@ static int mts_usb_probe(struct usb_interface *intf,
}
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" );

View file

@ -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

View file

@ -17,7 +17,6 @@ obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o
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

View file

@ -75,6 +75,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;
@ -116,7 +117,7 @@ static void adu_abort_transfers(struct adu_device *dev)
{
unsigned long flags;
if (dev->udev == NULL)
if (dev->disconnected)
return;
/* shutdown transfer */
@ -148,6 +149,7 @@ static void adu_delete(struct adu_device *dev)
kfree(dev->read_buffer_secondary);
kfree(dev->interrupt_in_buffer);
kfree(dev->interrupt_out_buffer);
usb_put_dev(dev->udev);
kfree(dev);
}
@ -243,7 +245,7 @@ static int adu_open(struct inode *inode, struct file *file)
}
dev = usb_get_intfdata(interface);
if (!dev || !dev->udev) {
if (!dev) {
retval = -ENODEV;
goto exit_no_device;
}
@ -326,7 +328,7 @@ static int adu_release(struct inode *inode, struct file *file)
}
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 +357,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
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 +522,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
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;
@ -665,7 +667,7 @@ static int adu_probe(struct usb_interface *interface,
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);
@ -764,14 +766,18 @@ static void adu_disconnect(struct usb_interface *interface)
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);
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->disconnected = 1;
mutex_unlock(&dev->mtx);
/* if the device is not opened, then we clean up right now */
if (!dev->open_count)
adu_delete(dev);

View file

@ -98,6 +98,7 @@ static void chaoskey_free(struct chaoskey *dev)
usb_free_urb(dev->urb);
kfree(dev->name);
kfree(dev->buf);
usb_put_intf(dev->interface);
kfree(dev);
}
}
@ -145,6 +146,8 @@ static int chaoskey_probe(struct usb_interface *interface,
if (dev == NULL)
goto out;
dev->interface = usb_get_intf(interface);
dev->buf = kmalloc(size, GFP_KERNEL);
if (dev->buf == NULL)
@ -174,8 +177,6 @@ static int chaoskey_probe(struct usb_interface *interface,
goto out;
}
dev->interface = interface;
dev->in_ep = in_ep;
if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID)

View file

@ -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;
};
/*--------------*/
@ -243,6 +244,7 @@ static inline void iowarrior_delete(struct iowarrior *dev)
kfree(dev->int_in_buffer);
usb_free_urb(dev->int_in_urb);
kfree(dev->read_queue);
usb_put_intf(dev->interface);
kfree(dev);
}
@ -424,11 +426,13 @@ static ssize_t iowarrior_write(struct file *file,
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 */
@ -764,11 +768,13 @@ static int iowarrior_probe(struct usb_interface *interface,
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);
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");
@ -866,8 +872,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
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);
@ -878,8 +882,7 @@ static void iowarrior_disconnect(struct usb_interface *interface)
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 ,
@ -887,10 +890,13 @@ static void iowarrior_disconnect(struct usb_interface *interface)
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);
} else {
/* no process is using the device, cleanup now */
mutex_unlock(&dev->mutex);
iowarrior_delete(dev);
}

View file

@ -153,6 +153,7 @@ MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in
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 */
@ -192,11 +193,9 @@ static void ld_usb_abort_transfers(struct ld_usb *dev)
/* shutdown transfer */
if (dev->interrupt_in_running) {
dev->interrupt_in_running = 0;
if (dev->intf)
usb_kill_urb(dev->interrupt_in_urb);
}
if (dev->interrupt_out_busy)
if (dev->intf)
usb_kill_urb(dev->interrupt_out_urb);
}
@ -205,8 +204,6 @@ static void ld_usb_abort_transfers(struct ld_usb *dev)
*/
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);
@ -263,7 +260,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
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,
@ -392,7 +389,7 @@ static int ld_usb_release(struct inode *inode, struct file *file)
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 */
@ -423,7 +420,7 @@ static __poll_t ld_usb_poll(struct file *file, poll_table *wait)
dev = file->private_data;
if (!dev->intf)
if (dev->disconnected)
return EPOLLERR | EPOLLHUP;
poll_wait(file, &dev->read_wait, wait);
@ -462,7 +459,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
}
/* 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;
@ -542,7 +539,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
}
/* 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;
@ -764,6 +761,9 @@ static void ld_usb_disconnect(struct usb_interface *intf)
/* 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 */
@ -771,7 +771,7 @@ static void ld_usb_disconnect(struct usb_interface *intf)
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);

View file

@ -179,7 +179,6 @@ static const struct usb_device_id tower_table[] = {
};
MODULE_DEVICE_TABLE (usb, tower_table);
static DEFINE_MUTEX(open_disc_mutex);
#define LEGO_USB_TOWER_MINOR_BASE 160
@ -191,6 +190,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 */
@ -290,14 +290,13 @@ static inline void lego_usb_tower_debug_data(struct device *dev,
*/
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);
kfree (dev->read_buffer);
kfree (dev->interrupt_in_buffer);
kfree (dev->interrupt_out_buffer);
usb_put_dev(dev->udev);
kfree (dev);
}
@ -332,18 +331,14 @@ static int tower_open (struct inode *inode, struct file *file)
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;
}
@ -351,12 +346,9 @@ static int tower_open (struct inode *inode, struct file *file)
/* 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,
@ -396,13 +388,14 @@ static int tower_open (struct inode *inode, struct file *file)
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);
@ -423,10 +416,9 @@ static int tower_release (struct inode *inode, struct file *file)
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;
@ -438,7 +430,8 @@ static int tower_release (struct inode *inode, struct file *file)
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 */
@ -456,10 +449,7 @@ static int tower_release (struct inode *inode, struct file *file)
unlock_exit:
mutex_unlock(&dev->lock);
exit:
mutex_unlock(&open_disc_mutex);
exit_nolock:
return retval;
}
@ -477,10 +467,9 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
if (dev->interrupt_in_running) {
dev->interrupt_in_running = 0;
mb();
if (dev->udev)
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);
}
@ -516,7 +505,7 @@ static __poll_t tower_poll (struct file *file, poll_table *wait)
dev = file->private_data;
if (!dev->udev)
if (dev->disconnected)
return EPOLLERR | EPOLLHUP;
poll_wait(file, &dev->read_wait, wait);
@ -563,7 +552,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
}
/* 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;
@ -649,7 +638,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
}
/* 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;
@ -759,7 +748,7 @@ static void tower_interrupt_in_callback (struct urb *urb)
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,
@ -822,8 +811,9 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
mutex_init(&dev->lock);
dev->udev = udev;
dev->udev = usb_get_dev(udev);
dev->open_count = 0;
dev->disconnected = 0;
dev->read_buffer = NULL;
dev->read_buffer_length = 0;
@ -891,8 +881,10 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
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;
}
@ -910,7 +902,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
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;
@ -942,23 +933,24 @@ static void tower_disconnect (struct usb_interface *interface)
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);
/* stop I/O */
usb_poison_urb(dev->interrupt_in_urb);
usb_poison_urb(dev->interrupt_out_urb);
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) {
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);

View file

@ -1,561 +0,0 @@
// SPDX-License-Identifier: GPL-2.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)
*
* 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");

View file

@ -1,20 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/* ----------------------------------------------------------------------
Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar)
---------------------------------------------------------------------- */
#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;
};

View file

@ -18,6 +18,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>
@ -57,6 +58,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)
@ -142,6 +145,13 @@ static ssize_t lcd_read(struct file *file, char __user * buffer,
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,
@ -158,6 +168,9 @@ static ssize_t lcd_read(struct file *file, char __user * buffer,
retval = bytes_read;
}
out_up_io:
up_read(&dev->io_rwsem);
return retval;
}
@ -237,11 +250,18 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer,
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,
@ -278,6 +298,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer,
the USB core will eventually free it entirely */
usb_free_urb(urb);
up_read(&dev->io_rwsem);
exit:
return count;
error_unanchor:
@ -285,7 +306,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer,
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;
}
@ -325,6 +347,7 @@ static int lcd_probe(struct usb_interface *interface,
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));
@ -422,6 +445,12 @@ static void lcd_disconnect(struct usb_interface *interface)
/* 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);

View file

@ -60,6 +60,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;
@ -107,6 +108,7 @@ static void yurex_delete(struct kref *kref)
dev->int_buffer, dev->urb->transfer_dma);
usb_free_urb(dev->urb);
}
usb_put_intf(dev->interface);
usb_put_dev(dev->udev);
kfree(dev);
}
@ -132,6 +134,7 @@ static void yurex_interrupt(struct urb *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",
@ -140,12 +143,13 @@ static void yurex_interrupt(struct urb *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 */
@ -177,7 +181,6 @@ static void yurex_interrupt(struct urb *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",
@ -204,7 +207,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
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;
@ -315,8 +318,9 @@ static void yurex_disconnect(struct usb_interface *interface)
/* 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 */
@ -404,7 +408,7 @@ static ssize_t yurex_read(struct file *file, char __user *buffer, size_t count,
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;
}
@ -439,7 +443,7 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
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;

View file

@ -207,6 +207,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 */

View file

@ -89,7 +89,7 @@ static void __usbhsf_pkt_del(struct usbhs_pkt *pkt)
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);
}

View file

@ -97,5 +97,6 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
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 */

View file

@ -721,8 +721,7 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
unsigned long flags;
usbhsg_pipe_disable(uep);
int ret = 0;
dev_dbg(dev, "set halt %d (pipe %d)\n",
halt, usbhs_pipe_number(pipe));
@ -730,6 +729,18 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
/******************** 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
@ -740,10 +751,11 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
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)

View file

@ -277,6 +277,21 @@ int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe)
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
*/

View file

@ -83,6 +83,7 @@ void usbhs_pipe_clear(struct usbhs_pipe *pipe);
void usbhs_pipe_clear_without_sequence(struct usbhs_pipe *pipe,
int needs_bfre, int bfre_enable);
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);

View file

@ -1020,6 +1020,9 @@ static const struct usb_device_id id_table_combined[] = {
/* 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 */
};

View file

@ -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
@ -688,6 +691,12 @@
#define BANDB_TTL3USB9M_PID 0xAC50
#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
*/

View file

@ -1741,8 +1741,8 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
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";

View file

@ -419,6 +419,7 @@ static void option_instat_callback(struct urb *urb);
#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
@ -1154,6 +1155,14 @@ static const struct usb_device_id option_ids[] = {
.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),
@ -1847,6 +1856,8 @@ static const struct usb_device_id option_ids[] = {
.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) },

View file

@ -311,10 +311,7 @@ static void serial_cleanup(struct tty_struct *tty)
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_serial_put(serial);
module_put(owner);

View file

@ -59,6 +59,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)
@ -71,6 +72,7 @@ static void skel_delete(struct kref *kref)
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);
@ -122,10 +124,7 @@ static int skel_release(struct inode *inode, struct file *file)
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);
/* decrement the count on our device */
kref_put(&dev->kref, skel_delete);
@ -238,7 +237,7 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count,
if (rv < 0)
return rv;
if (!dev->interface) { /* disconnect() was called */
if (dev->disconnected) { /* disconnect() was called */
rv = -ENODEV;
goto exit;
}
@ -420,7 +419,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer,
/* 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;
@ -505,7 +504,7 @@ static int skel_probe(struct usb_interface *interface,
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 */
@ -571,7 +570,7 @@ static void skel_disconnect(struct usb_interface *interface)
/* 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);

View file

@ -511,7 +511,7 @@ static int process_leaf(struct btrfs_root *root,
struct btrfs_extent_data_ref *dref;
struct btrfs_shared_data_ref *sref;
u32 count;
int i = 0, tree_block_level = 0, ret;
int i = 0, tree_block_level = 0, ret = 0;
struct btrfs_key key;
int nritems = btrfs_header_nritems(leaf);

View file

@ -2860,7 +2860,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
* 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;
@ -2868,10 +2869,10 @@ static int update_log_root(struct btrfs_trans_handle *trans,
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;
}
@ -2969,6 +2970,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
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;
@ -3032,17 +3034,25 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
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
@ -3063,6 +3073,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
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)) {
/* atomic_dec_and_test implies a barrier */
cond_wake_up_nomb(&log_root_tree->log_writer_wait);

View file

@ -840,10 +840,16 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
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 {
@ -854,7 +860,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
* 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;

View file

@ -252,6 +252,12 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
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;
@ -1835,13 +1841,12 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
{
struct cifsFileInfo *open_file = NULL;
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
/* only filter by fsuid on multiuser mounts */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
fsuid_only = false;
spin_lock(&tcon->open_file_lock);
spin_lock(&cifs_inode->open_file_lock);
/* we could simply get the first_list_entry since write-only entries
are always at the end of the list but since the first entry might
have a close pending, we go through the whole list */
@ -1853,7 +1858,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
/* found a good file */
/* lock it so it will not be closed on us */
cifsFileInfo_get(open_file);
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
return open_file;
} /* else might as well continue, and look for
another, or simply have the caller reopen it
@ -1861,7 +1866,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
} else /* write only file */
break; /* write only files are last so must be done */
}
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
return NULL;
}
@ -1870,7 +1875,6 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
{
struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon;
bool any_available = false;
int rc;
unsigned int refind = 0;
@ -1886,16 +1890,15 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
}
cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
tcon = cifs_sb_master_tcon(cifs_sb);
/* only filter by fsuid on multiuser mounts */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
fsuid_only = false;
spin_lock(&tcon->open_file_lock);
spin_lock(&cifs_inode->open_file_lock);
refind_writable:
if (refind > MAX_REOPEN_ATT) {
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
return NULL;
}
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
@ -1907,7 +1910,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
if (!open_file->invalidHandle) {
/* found a good writable file */
cifsFileInfo_get(open_file);
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
return open_file;
} else {
if (!inv_file)
@ -1926,7 +1929,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
cifsFileInfo_get(inv_file);
}
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
if (inv_file) {
rc = cifs_reopen_file(inv_file, false);
@ -1940,7 +1943,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
cifsFileInfo_put(inv_file);
++refind;
inv_file = NULL;
spin_lock(&tcon->open_file_lock);
spin_lock(&cifs_inode->open_file_lock);
goto refind_writable;
}
}
@ -4001,17 +4004,15 @@ static int cifs_readpage(struct file *file, struct page *page)
static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *open_file;
struct cifs_tcon *tcon =
cifs_sb_master_tcon(CIFS_SB(cifs_inode->vfs_inode.i_sb));
spin_lock(&tcon->open_file_lock);
spin_lock(&cifs_inode->open_file_lock);
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
return 1;
}
}
spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_inode->open_file_lock);
return 0;
}

View file

@ -410,6 +410,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* 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 inode **pinode,
/* 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;
}
@ -926,6 +928,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
/* 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;
}
@ -933,6 +936,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
/* 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;
}

View file

@ -2444,11 +2444,11 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
}
}
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 */
@ -2456,7 +2456,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 */
@ -2465,7 +2465,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 */
@ -2473,7 +2473,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 */
@ -2483,7 +2483,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) !=
@ -2492,7 +2492,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);
@ -2508,7 +2508,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 ||
@ -2517,28 +2517,28 @@ 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 ||
raw_super->hot_ext_count > F2FS_MAX_EXTENSION ||
@ -2549,7 +2549,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
le32_to_cpu(raw_super->extension_count),
raw_super->hot_ext_count,
F2FS_MAX_EXTENSION);
return 1;
return -EFSCORRUPTED;
}
if (le32_to_cpu(raw_super->cp_payload) >
@ -2558,7 +2558,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 */
@ -2570,12 +2570,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;
}
@ -2869,11 +2869,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;
}

View file

@ -86,58 +86,47 @@ int dcache_dir_close(struct inode *inode, struct file *file)
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;
// 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 *file, loff_t offset, int whence)
return -EINVAL;
}
if (offset != file->f_pos) {
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;
struct dentry *to = NULL;
struct list_head *p;
file->f_pos = offset;
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);
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, struct dir_context *ctx)
{
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);

View file

@ -122,32 +122,49 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
}
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)
{
int i;
ssize_t count;
struct nfs_direct_mirror *mirror = &dreq->mirrors[hdr->pgio_mirror_idx];
WARN_ON_ONCE(dreq->count >= dreq->max_count);
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 (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;
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
dreq->error = hdr->error;
else /* Clear outstanding error if this is EOF */
dreq->error = 0;
}
/* update the dreq->count by finding the minimum agreed count from all
* mirrors */
count = dreq->mirrors[0].count;
for (i = 1; i < dreq->mirror_count; i++)
count = min(count, dreq->mirrors[i].count);
dreq->count = count;
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)
{
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;
if (hdr_end > dreq->io_start)
dreq_len = hdr_end - dreq->io_start;
nfs_direct_handle_truncated(dreq, hdr, dreq_len);
if (dreq_len > dreq->max_count)
dreq_len = dreq->max_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(struct nfs_pgio_header *hdr)
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(struct nfs_direct_req *dreq)
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(struct nfs_pgio_header *hdr)
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;

View file

@ -1472,8 +1472,11 @@ struct acpi_pptt_processor {
/* Flags */
#define ACPI_PPTT_PHYSICAL_PACKAGE (1) /* Physical package */
#define ACPI_PPTT_ACPI_PROCESSOR_ID_VALID (2) /* ACPI Processor ID valid */
#define ACPI_PPTT_PHYSICAL_PACKAGE (1)
#define ACPI_PPTT_ACPI_PROCESSOR_ID_VALID (1<<1)
#define ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD (1<<2) /* ACPI 6.3 */
#define ACPI_PPTT_ACPI_LEAF_NODE (1<<3) /* ACPI 6.3 */
#define ACPI_PPTT_ACPI_IDENTICAL (1<<4) /* ACPI 6.3 */
/* 1: Cache Type Structure */

View file

@ -1291,10 +1291,15 @@ static inline int lpit_read_residency_count_address(u64 *address)
#endif
#ifdef CONFIG_ACPI_PPTT
int acpi_pptt_cpu_is_thread(unsigned int cpu);
int find_acpi_cpu_topology(unsigned int cpu, int level);
int find_acpi_cpu_topology_package(unsigned int cpu);
int find_acpi_cpu_cache_topology(unsigned int cpu, int level);
#else
static inline int acpi_pptt_cpu_is_thread(unsigned int cpu)
{
return -EINVAL;
}
static inline int find_acpi_cpu_topology(unsigned int cpu, int level)
{
return -EINVAL;

View file

@ -225,7 +225,7 @@ enum hwmon_power_attributes {
#define HWMON_P_LABEL BIT(hwmon_power_label)
#define HWMON_P_ALARM BIT(hwmon_power_alarm)
#define HWMON_P_CAP_ALARM BIT(hwmon_power_cap_alarm)
#define HWMON_P_MIN_ALARM BIT(hwmon_power_max_alarm)
#define HWMON_P_MIN_ALARM BIT(hwmon_power_min_alarm)
#define HWMON_P_MAX_ALARM BIT(hwmon_power_max_alarm)
#define HWMON_P_LCRIT_ALARM BIT(hwmon_power_lcrit_alarm)
#define HWMON_P_CRIT_ALARM BIT(hwmon_power_crit_alarm)

View file

@ -426,7 +426,7 @@ static int hw_breakpoint_parse(struct perf_event *bp,
int register_perf_hw_breakpoint(struct perf_event *bp)
{
struct arch_hw_breakpoint hw;
struct arch_hw_breakpoint hw = { };
int err;
err = reserve_bp_slot(bp);
@ -474,7 +474,7 @@ int
modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr,
bool check)
{
struct arch_hw_breakpoint hw;
struct arch_hw_breakpoint hw = { };
int err;
err = hw_breakpoint_parse(bp, attr, &hw);

View file

@ -2634,7 +2634,7 @@ int sysctl_max_threads(struct ctl_table *table, int write,
struct ctl_table t;
int ret;
int threads = max_threads;
int min = MIN_THREADS;
int min = 1;
int max = MAX_THREADS;
t = *table;
@ -2646,7 +2646,7 @@ int sysctl_max_threads(struct ctl_table *table, int write,
if (ret || !write)
return ret;
set_max_threads(threads);
max_threads = threads;
return 0;
}

View file

@ -149,6 +149,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

View file

@ -3558,21 +3558,22 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
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;
@ -3602,13 +3603,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
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;
@ -3620,7 +3621,6 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
/* Failed */
free_ftrace_hash(iter->hash);
trace_parser_put(&iter->parser);
kfree(iter);
}
} else
file->private_data = iter;
@ -3628,6 +3628,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
out_unlock:
mutex_unlock(&ops->func_hash->regex_lock);
out:
if (ret) {
kfree(iter);
if (tr)
trace_array_put(tr);
}
return ret;
}
@ -5025,6 +5032,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
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;

View file

@ -4154,9 +4154,14 @@ static int show_traces_open(struct inode *inode, struct file *file)
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;
@ -4164,6 +4169,14 @@ static int show_traces_open(struct inode *inode, struct file *file)
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)
@ -4194,8 +4207,8 @@ static const struct file_operations tracing_fops = {
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

View file

@ -150,7 +150,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)
@ -256,6 +256,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:

View file

@ -358,6 +358,9 @@ void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio)
* "hierarchy" or "local").
*
* To be used as memcg event method.
*
* Return: 0 on success, -ENOMEM on memory failure or -EINVAL if @args could
* not be parsed.
*/
int vmpressure_register_event(struct mem_cgroup *memcg,
struct eventfd_ctx *eventfd, const char *args)
@ -365,7 +368,7 @@ int vmpressure_register_event(struct mem_cgroup *memcg,
struct vmpressure *vmpr = memcg_to_vmpressure(memcg);
struct vmpressure_event *ev;
enum vmpressure_modes mode = VMPRESSURE_NO_PASSTHROUGH;
enum vmpressure_levels level = -1;
enum vmpressure_levels level;
char *spec, *spec_orig;
char *token;
int ret = 0;
@ -378,20 +381,18 @@ int vmpressure_register_event(struct mem_cgroup *memcg,
/* Find required level */
token = strsep(&spec, ",");
level = match_string(vmpressure_str_levels, VMPRESSURE_NUM_LEVELS, token);
if (level < 0) {
ret = level;
ret = match_string(vmpressure_str_levels, VMPRESSURE_NUM_LEVELS, token);
if (ret < 0)
goto out;
}
level = ret;
/* Find optional mode */
token = strsep(&spec, ",");
if (token) {
mode = match_string(vmpressure_str_modes, VMPRESSURE_NUM_MODES, token);
if (mode < 0) {
ret = mode;
ret = match_string(vmpressure_str_modes, VMPRESSURE_NUM_MODES, token);
if (ret < 0)
goto out;
}
mode = ret;
}
ev = kzalloc(sizeof(*ev), GFP_KERNEL);
@ -407,6 +408,7 @@ int vmpressure_register_event(struct mem_cgroup *memcg,
mutex_lock(&vmpr->events_lock);
list_add(&ev->node, &vmpr->events);
mutex_unlock(&vmpr->events_lock);
ret = 0;
out:
kfree(spec_orig);
return ret;

View file

@ -394,7 +394,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
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 jit_buf_desc *jd, union jr_entry *jr)
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 jit_buf_desc *jd, union jr_entry *jr)
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);

View file

@ -230,14 +230,14 @@ static int detect_kbuild_dir(char **kbuild_dir)
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)