/* * Copyright (C) 2014-2015 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation version 2. * * This program is distributed "as is" WITHOUT ANY WARRANTY of any * kind, whether express or implied; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __CYGNUS_SSP_H__ #define __CYGNUS_SSP_H__ #define CYGNUS_TDM_DAI_MAX_SLOTS 16 #define CYGNUS_MAX_PLAYBACK_PORTS 4 #define CYGNUS_MAX_CAPTURE_PORTS 3 #define CYGNUS_MAX_I2S_PORTS 3 #define CYGNUS_MAX_PORTS CYGNUS_MAX_PLAYBACK_PORTS #define CYGNUS_AUIDO_MAX_NUM_CLKS 3 #define CYGNUS_SSP_FRAMEBITS_DIV 1 #define CYGNUS_SSPMODE_I2S 0 #define CYGNUS_SSPMODE_TDM 1 #define CYGNUS_SSPMODE_UNKNOWN -1 #define CYGNUS_SSP_CLKSRC_PLL 0 /* Max string length of our dt property names */ #define PROP_LEN_MAX 40 struct ringbuf_regs { unsigned rdaddr; unsigned wraddr; unsigned baseaddr; unsigned endaddr; unsigned fmark; /* freemark for play, fullmark for caputure */ unsigned period_bytes; unsigned buf_size; }; #define RINGBUF_REG_PLAYBACK(num) ((struct ringbuf_regs) { \ .rdaddr = SRC_RBUF_ ##num## _RDADDR_OFFSET, \ .wraddr = SRC_RBUF_ ##num## _WRADDR_OFFSET, \ .baseaddr = SRC_RBUF_ ##num## _BASEADDR_OFFSET, \ .endaddr = SRC_RBUF_ ##num## _ENDADDR_OFFSET, \ .fmark = SRC_RBUF_ ##num## _FREE_MARK_OFFSET, \ .period_bytes = 0, \ .buf_size = 0, \ }) #define RINGBUF_REG_CAPTURE(num) ((struct ringbuf_regs) { \ .rdaddr = DST_RBUF_ ##num## _RDADDR_OFFSET, \ .wraddr = DST_RBUF_ ##num## _WRADDR_OFFSET, \ .baseaddr = DST_RBUF_ ##num## _BASEADDR_OFFSET, \ .endaddr = DST_RBUF_ ##num## _ENDADDR_OFFSET, \ .fmark = DST_RBUF_ ##num## _FULL_MARK_OFFSET, \ .period_bytes = 0, \ .buf_size = 0, \ }) enum cygnus_audio_port_type { PORT_TDM, PORT_SPDIF, }; struct cygnus_ssp_regs { u32 i2s_stream_cfg; u32 i2s_cfg; u32 i2s_cap_stream_cfg; u32 i2s_cap_cfg; u32 i2s_mclk_cfg; u32 bf_destch_ctrl; u32 bf_destch_cfg; u32 bf_sourcech_ctrl; u32 bf_sourcech_cfg; u32 bf_sourcech_grp; }; struct cygnus_track_clk { bool cap_en; bool play_en; bool cap_clk_en; bool play_clk_en; }; struct cygnus_aio_port { int portnum; int mode; bool is_slave; int streams_on; /* will be 0 if both capture and play are off */ int fsync_width; int port_type; u32 mclk; u32 lrclk; u32 bit_per_frame; u32 pll_clk_num; struct cygnus_audio *cygaud; struct cygnus_ssp_regs regs; struct ringbuf_regs play_rb_regs; struct ringbuf_regs capture_rb_regs; struct snd_pcm_substream *play_stream; struct snd_pcm_substream *capture_stream; struct cygnus_track_clk clk_trace; }; struct cygnus_audio { struct cygnus_aio_port portinfo[CYGNUS_MAX_PORTS]; int irq_num; void __iomem *audio; struct device *dev; void __iomem *i2s_in; struct clk *audio_clk[CYGNUS_AUIDO_MAX_NUM_CLKS]; int active_ports; unsigned long vco_rate; }; extern int cygnus_ssp_get_mode(struct snd_soc_dai *cpu_dai); extern int cygnus_ssp_add_pll_tweak_controls(struct snd_soc_pcm_runtime *rtd); extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai, int len); extern int cygnus_soc_platform_register(struct device *dev, struct cygnus_audio *cygaud); extern int cygnus_soc_platform_unregister(struct device *dev); extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai, int len); #endif ext.git/commit/tools/perf/arch/arm/util/unwind-libunwind.c?id=966d2b04e070bc040319aaebfec09e0144dc3341'>unwind-libunwind.c
diff options
context:
space:
mode:
authorDouglas Miller <dougmill@linux.vnet.ibm.com>2017-01-28 06:42:20 -0600
committerTejun Heo <tj@kernel.org>2017-01-28 07:49:42 -0500
commit966d2b04e070bc040319aaebfec09e0144dc3341 (patch)
tree4b96156e3d1dd4dfd6039b7c219c9dc4616da52d /tools/perf/arch/arm/util/unwind-libunwind.c
parent1b1bc42c1692e9b62756323c675a44cb1a1f9dbd (diff)
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+
Diffstat (limited to 'tools/perf/arch/arm/util/unwind-libunwind.c')