/*
* wm8900.h -- WM890 Soc Audio driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _WM8900_H
#define _WM8900_H
#define WM8900_FLL 1
#define WM8900_BCLK_DIV 1
#define WM8900_ADC_CLKDIV 2
#define WM8900_DAC_CLKDIV 3
#define WM8900_ADC_LRCLK 4
#define WM8900_DAC_LRCLK 5
#define WM8900_OPCLK_DIV 6
#define WM8900_LRCLK_MODE 7
#define WM8900_BCLK_DIV_1 0x00
#define WM8900_BCLK_DIV_1_5 0x02
#define WM8900_BCLK_DIV_2 0x04
#define WM8900_BCLK_DIV_3 0x06
#define WM8900_BCLK_DIV_4 0x08
#define WM8900_BCLK_DIV_5_5 0x0a
#define WM8900_BCLK_DIV_6 0x0c
#define WM8900_BCLK_DIV_8 0x0e
#define WM8900_BCLK_DIV_11 0x10
#define WM8900_BCLK_DIV_12 0x12
#define WM8900_BCLK_DIV_16 0x14
#define WM8900_BCLK_DIV_22 0x16
#define WM8900_BCLK_DIV_24 0x18
#define WM8900_BCLK_DIV_32 0x1a
#define WM8900_BCLK_DIV_44 0x1c
#define WM8900_BCLK_DIV_48 0x1e
#define WM8900_ADC_CLKDIV_1 0x00
#define WM8900_ADC_CLKDIV_1_5 0x20
#define WM8900_ADC_CLKDIV_2 0x40
#define WM8900_ADC_CLKDIV_3 0x60
#define WM8900_ADC_CLKDIV_4 0x80
#define WM8900_ADC_CLKDIV_5_5 0xa0
#define WM8900_ADC_CLKDIV_6 0xc0
#define WM8900_DAC_CLKDIV_1 0x00
#define WM8900_DAC_CLKDIV_1_5 0x04
#define WM8900_DAC_CLKDIV_2 0x08
#define WM8900_DAC_CLKDIV_3 0x0c
#define WM8900_DAC_CLKDIV_4 0x10
#define WM8900_DAC_CLKDIV_5_5 0x14
#define WM8900_DAC_CLKDIV_6 0x18
#endif
='tabs'>
percpu-refcount: fix reference leak during percpu-atomic transition
percpu_ref_tryget() and percpu_ref_tryget_live() should return
"true" IFF they acquire a reference. But the return value from
atomic_long_inc_not_zero() is a long and may have high bits set,
e.g. PERCPU_COUNT_BIAS, and the return value of the tryget routines
is bool so the reference may actually be acquired but the routines
return "false" which results in a reference leak since the caller
assumes it does not need to do a corresponding percpu_ref_put().
This was seen when performing CPU hotplug during I/O, as hangs in
blk_mq_freeze_queue_wait where percpu_ref_kill (blk_mq_freeze_queue_start)
raced with percpu_ref_tryget (blk_mq_timeout_work).
Sample stack trace:
__switch_to+0x2c0/0x450
__schedule+0x2f8/0x970
schedule+0x48/0xc0
blk_mq_freeze_queue_wait+0x94/0x120
blk_mq_queue_reinit_work+0xb8/0x180
blk_mq_queue_reinit_prepare+0x84/0xa0
cpuhp_invoke_callback+0x17c/0x600
cpuhp_up_callbacks+0x58/0x150
_cpu_up+0xf0/0x1c0
do_cpu_up+0x120/0x150
cpu_subsys_online+0x64/0xe0
device_online+0xb4/0x120
online_store+0xb4/0xc0
dev_attr_store+0x68/0xa0
sysfs_kf_write+0x80/0xb0
kernfs_fop_write+0x17c/0x250
__vfs_write+0x6c/0x1e0
vfs_write+0xd0/0x270
SyS_write+0x6c/0x110
system_call+0x38/0xe0
Examination of the queue showed a single reference (no PERCPU_COUNT_BIAS,
and __PERCPU_REF_DEAD, __PERCPU_REF_ATOMIC set) and no requests.
However, conditions at the time of the race are count of PERCPU_COUNT_BIAS + 0
and __PERCPU_REF_DEAD and __PERCPU_REF_ATOMIC set.
The fix is to make the tryget routines use an actual boolean internally instead
of the atomic long result truncated to a int.
Fixes: e625305b3907 percpu-refcount: make percpu_ref based on longs instead of ints
Link: https://bugzilla.kernel.org/show_bug.cgi?id=190751
Signed-off-by: Douglas Miller <dougmill@linux.vnet.ibm.com>
Reviewed-by: Jens Axboe <axboe@fb.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Fixes: e625305b3907 ("percpu-refcount: make percpu_ref based on longs instead of ints")
Cc: stable@vger.kernel.org # v3.18+