5.4.69-rc1 review
Subsystems (10)
Greg Kroah-Hartman
maintainerPATCH 120/388 locking/lockdep: Decrement IRQ context counters when removing lock chain
In reply to Greg Kroah-HartmanFrom: Waiman Long <[email protected]>
[ Upstream commit b3b9c187dc2544923a601733a85352b9ddaba9b3 ]
There are currently three counters to track the IRQ context of a lock chain - nr_hardirq_chains, nr_softirq_chains and nr_process_chains. They are incremented when a new lock chain is added, but they are not decremented when a lock chain is removed. That causes some of the statistic counts reported by /proc/lockdep_stats to be incorrect. IRQ
Fix that by decrementing the right counter when a lock chain is removed.
Since inc_chains() no longer accesses hardirq_context and softirq_context directly, it is moved out from the CONFIG_TRACE_IRQFLAGS conditional compilation block.
--- kernel/locking/lockdep.c | 40 +++++++++++++++++------------- kernel/locking/lockdep_internals.h | 6 +++++ 2 files changed, 29 insertions(+), 17 deletions(-)
kernel/locking/lockdep.c +23 -17
@@ -2302,18 +2302,6 @@ static int check_irq_usage(struct task_struct *curr, struct held_lock *prev,return 0 ; } -static void inc_chains (void ) -{ -if (current->hardirq_context) - nr_hardirq_chains++; -else { -if (current->softirq_context) - nr_softirq_chains++; -else - nr_process_chains++; - } -} -#else static inline int check_irq_usage(struct task_struct *curr,
@@ -2321,13 +2309,27 @@ static inline int check_irq_usage(struct task_struct *curr, {return 1 ; } +#endif /* CONFIG_TRACE_IRQFLAGS */ -static inline void inc_chains (void ) +static void inc_chains (int irq_context) { - nr_process_chains++; +if (irq_context &LOCK_CHAIN_HARDIRQ_CONTEXT ) + nr_hardirq_chains++; +else if (irq_context &LOCK_CHAIN_SOFTIRQ_CONTEXT ) + nr_softirq_chains++; +else + nr_process_chains++; } -#endif /* CONFIG_TRACE_IRQFLAGS */ +static void dec_chains (int irq_context) +{ +if (irq_context &LOCK_CHAIN_HARDIRQ_CONTEXT ) + nr_hardirq_chains--; +else if (irq_context &LOCK_CHAIN_SOFTIRQ_CONTEXT ) + nr_softirq_chains--; +else + nr_process_chains--; +}static void print_deadlock_scenario (struct held_lock *nxt,struct held_lock *prv)
@@ -2847,7 +2849,7 @@ static inline int add_chain_cache(struct task_struct *curr,hlist_add_head_rcu (&chain->entry, hash_head);debug_atomic_inc (chain_lookup_misses); -inc_chains (); +inc_chains (chain->irq_context);return 1 ; }
@@ -3600,7 +3602,8 @@ lock_used:static inline unsigned int task_irq_context (struct task_struct *task) { -return 2 * !!task->hardirq_context + !!task->softirq_context; +return LOCK_CHAIN_HARDIRQ_CONTEXT * !!task->hardirq_context + +LOCK_CHAIN_SOFTIRQ_CONTEXT * !!task->softirq_context; } static int separate_irq_context(struct task_struct *curr,
@@ -4805,6 +4808,8 @@ recalc:return ;/* Overwrite the chain key for concurrent RCU readers. */ WRITE_ONCE (chain->chain_key, chain_key); +dec_chains (chain->irq_context); +/* * Note: calling hlist_del_rcu() from inside a * hlist_for_each_entry_rcu() loop is safe.
@@ -4826,6 +4831,7 @@ recalc: } *new_chain = *chain;hlist_add_head_rcu (&new_chain->entry,chainhashentry (chain_key)); +inc_chains (new_chain->irq_context);#endif }
kernel/locking/lockdep_internals.h +6 -0
@@ -106,6 +106,12 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ =#define STACK_TRACE_HASH_SIZE 16384#endif +/* +* Bit definitions for lock_chain.irq_context +*/ +#define LOCK_CHAIN_SOFTIRQ_CONTEXT (1 << 0) +#define LOCK_CHAIN_HARDIRQ_CONTEXT (1 << 1) +#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS)#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 121/388 clk: stratix10: use do_div() for 64-bit calculation
In reply to Greg Kroah-HartmanFrom: Dinh Nguyen <[email protected]>
[ Upstream commit cc26ed7be46c5f5fa45f3df8161ed7ca3c4d318c ]
do_div() macro to perform u64 division and guards against overflow if the result is too large for the unsigned long return type.
--- drivers/clk/socfpga/clk-pll-s10.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/clk/socfpga/clk-pll-s10.c +3 -1
@@ -39,7 +39,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,/* read VCO1 reg for numerator and denominator */ reg =readl (socfpgaclk->hw.reg); refdiv = (reg &SOCFPGA_PLL_REFDIV_MASK ) >>SOCFPGA_PLL_REFDIV_SHIFT ; - vco_freq = (unsigned long long )parent_rate / refdiv; + + vco_freq = parent_rate; +do_div (vco_freq, refdiv);/* Read mdiv and fdiv from the fdbck register */ reg =readl (socfpgaclk->hw.reg +0x4 );
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 122/388 crypto: chelsio - This fixes the kernel panic which occurs during a libkcapi test
In reply to Greg Kroah-HartmanFrom: Ayush Sawal <[email protected]>
[ Upstream commit 9195189e00a7db55e7d448cee973cae87c5a3c71 ]
The libkcapi test which causes kernel panic is
aead asynchronous vmsplice multiple test.
./bin/kcapi -v -d 4 -x 10 -c "ccm(aes)"
-q 4edb58e8d5eb6bc711c43a6f3693daebde2e5524f1b55297abb29f003236e43d -t a7877c99 -n 674742abd0f5ba -k 2861fd0253705d7875c95ba8a53171b4 -a fb7bc304a3909e66e2e0c5ef952712dd884ce3e7324171369f2c5db1adc48c7d
This patch avoids dma_mapping of a zero length sg which causes the panic, by using sg_nents_for_len which maps only upto a specific length
--- drivers/crypto/chelsio/chcr_algo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/crypto/chelsio/chcr_algo.c +3 -2
@@ -2480,8 +2480,9 @@ int chcr_aead_dma_map(struct device *dev,else reqctx->b0_dma =0 ;if (req->src == req->dst) { - error =dma_map_sg (dev, req->src,sg_nents (req->src), -DMA_BIDIRECTIONAL ); + error =dma_map_sg (dev, req->src, +sg_nents_for_len (req->src, dst_size), +DMA_BIDIRECTIONAL );if (!error) goto err; }else {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 123/388 mt76: clear skb pointers from rx aggregation reorder buffer during cleanup
In reply to Greg Kroah-HartmanFrom: Felix Fietkau <[email protected]>
[ Upstream commit 9379df2fd9234e3b67a23101c2370c99f6af6d77 ]
During the cleanup of the aggregation session, a rx handler (or release timer) on another CPU might still hold a pointer to the reorder buffer and could attempt to release some packets.
Clearing pointers during cleanup avoids a theoretical use-after-free bug here.
--- drivers/net/wireless/mediatek/mt76/agg-rx.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/agg-rx.c +1 -0
@@ -268,6 +268,7 @@ static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid)if (!skb)continue ; + tid->reorder_buf[i] =NULL ; tid->nframes--;dev_kfree_skb (skb); }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 124/388 mt76: fix handling full tx queues in mt76_dma_tx_queue_skb_raw
In reply to Greg Kroah-HartmanFrom: Felix Fietkau <[email protected]>
[ Upstream commit 93eaec7625f13cffb593b471405b017c7e64d4ee ]
Fixes a theoretical issue where it could potentially overwrite an existing descriptor entry (and leaking its skb)
--- drivers/net/wireless/mediatek/mt76/dma.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/dma.c +8 -1
@@ -261,10 +261,13 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid,struct mt76_queue_buf buf;dma_addr_t addr; +if (q->queued +1 >= q->ndesc -1 ) + goto error; + addr =dma_map_single (dev->dev, skb->data, skb->len,DMA_TO_DEVICE );if (unlikely (dma_mapping_error (dev->dev, addr))) -return -ENOMEM ; + goto error; buf.addr = addr; buf.len = skb->len;
@@ -275,6 +278,10 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid,spin_unlock_bh (&q->lock);return 0 ; + +error: +dev_kfree_skb (skb); +return -ENOMEM ; } static int
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 125/388 ALSA: usb-audio: Dont create a mixer element with bogus volume range
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
[ Upstream commit e9a0ef0b5ddcbc0d56c65aefc0f18d16e6f71207 ]
Some USB-audio descriptors provide a bogus volume range (e.g. volume min and max are identical), which confuses user-space. This patch makes the driver skipping such a control element.
--- sound/usb/mixer.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
sound/usb/mixer.c +10 -0
@@ -1684,6 +1684,16 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,/* get min/max values */ get_min_max_with_quirks (cval,0 , kctl); +/* skip a bogus volume range */ +if (cval->max <= cval->min) { +usb_audio_dbg (mixer->chip, +"[%d] FU [%s] skipped due to invalid volume\n" , + cval->head.id, kctl->id.name); +snd_ctl_free_one (kctl); +return ; + } + +if (control ==UAC_FU_VOLUME ) {check_mapped_dB (map, cval);if (cval->dBmin < cval->dBmax || !cval->initialized) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 126/388 perf test: Fix test trace+probe_vfs_getname.sh on s390
In reply to Greg Kroah-HartmanFrom: Thomas Richter <[email protected]>
[ Upstream commit 2bbc83537614517730e9f2811195004b712de207 ]
This test places a kprobe to function getname_flags() in the kernel which has the following prototype:
struct filename *getname_flags(const char __user *filename, int flags, int *empty)
The 'filename' argument points to a filename located in user space memory.
Looking at commit 88903c464321c ("tracing/probe: Add ustring type for user-space string") the kprobe should indicate that user space memory is accessed.
Output before:
[root@m35lp76 perf]# ./perf test 66 67
66: Use vfs_getname probe to get syscall args filenames : FAILED!
67: Check open filename arg using perf trace + vfs_getname: FAILED! [root@m35lp76 perf]#
Output after:
[root@m35lp76 perf]# ./perf test 66 67
66: Use vfs_getname probe to get syscall args filenames : Ok
67: Check open filename arg using perf trace + vfs_getname: Ok [root@m35lp76 perf]#
Comments from Masami Hiramatsu:
This bug doesn't happen on x86 or other archs on which user address space and kernel address space is the same. On some arches (ppc64 in this case?) user address space is partially or completely the same as kernel address space.
(Yes, they switch the world when running into the kernel) In this case, we need to use different data access functions for each space.
That is why I introduced the "ustring" type for kprobe events.
As far as I can see, Thomas's patch is sane. Thomas, could you show us your result on your test environment?
Comments from Thomas Richter:
Test results for s/390 included above.
--- tools/perf/tests/shell/lib/probe_vfs_getname.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/shell/lib/probe_vfs_getname.sh +1 -1
@@ -14,7 +14,7 @@ add_probe_vfs_getname() { if [ $had_vfs_getname -eq 1 ] ; then line=$(perf probe -L getname_flags 2>&1 | egrep 'result.*=.*filename;' | sed -r 's/[[:space:]]+([[:digit:]]+)[[:space:]]+result->uptr.*/\1/') perf probe -q "vfs_getname=getname_flags:${line} pathname=result->name:string" || \ - perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:string" + perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:ustring" fi }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 127/388 RDMA/rxe: Fix configuration of atomic queue pair attributes
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
[ Upstream commit fb3063d31995cc4cf1d47a406bb61d6fb1b1d58d ]
Quoted 1 line
From the comment above the definition of the
roundup_pow_of_two()macro:
The result is undefined when n == 0.
Hence only pass positive values to roundup_pow_of_two(). This patch fixes the following UBSAN complaint:
UBSAN: Undefined behaviour in ./include/linux/log2.h:57:13 shift exponent 64 is too large for 64-bit type 'long unsigned int' Call Trace: dump_stack+0xa5/0xe6 ubsan_epilogue+0x9/0x26 __ubsan_handle_shift_out_of_bounds.cold+0x4c/0xf9 rxe_qp_from_attr.cold+0x37/0x5d [rdma_rxe] rxe_modify_qp+0x59/0x70 [rdma_rxe] _ib_modify_qp+0x5aa/0x7c0 [ib_core] ib_modify_qp+0x3b/0x50 [ib_core] cma_modify_qp_rtr+0x234/0x260 [rdma_cm] __rdma_accept+0x1a7/0x650 [rdma_cm] nvmet_rdma_cm_handler+0x1286/0x14cd [nvmet_rdma] cma_cm_event_handler+0x6b/0x330 [rdma_cm] cma_ib_req_handler+0xe60/0x22d0 [rdma_cm] cm_process_work+0x30/0x140 [ib_cm] cm_req_handler+0x11f4/0x1cd0 [ib_cm] cm_work_handler+0xb8/0x344e [ib_cm] process_one_work+0x569/0xb60 worker_thread+0x7a/0x5d0 kthread+0x1e6/0x210 ret_from_fork+0x24/0x30
--- drivers/infiniband/sw/rxe/rxe_qp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/infiniband/sw/rxe/rxe_qp.c +4 -3
@@ -592,15 +592,16 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,int err;if (mask &IB_QP_MAX_QP_RD_ATOMIC ) { -int max_rd_atomic =__roundup_pow_of_two (attr->max_rd_atomic); +int max_rd_atomic = attr->max_rd_atomic ? +roundup_pow_of_two (attr->max_rd_atomic) :0 ; qp->attr.max_rd_atomic = max_rd_atomic;atomic_set (&qp->req.rd_atomic, max_rd_atomic); }if (mask &IB_QP_MAX_DEST_RD_ATOMIC ) { -int max_dest_rd_atomic = -__roundup_pow_of_two (attr->max_dest_rd_atomic); +int max_dest_rd_atomic = attr->max_dest_rd_atomic ? +roundup_pow_of_two (attr->max_dest_rd_atomic) :0 ; qp->attr.max_dest_rd_atomic = max_dest_rd_atomic;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 128/388 KVM: x86: fix incorrect comparison in trace event
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
[ Upstream commit 147f1a1fe5d7e6b01b8df4d0cbd6f9eaf6b6c73b ]
The "u" field in the event has three states, -1/0/1. Using u8 however means that comparison with -1 will always fail, so change to signed char.
--- arch/x86/kvm/mmutrace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/mmutrace.h +1 -1
@@ -339,7 +339,7 @@ TRACE_EVENT(/* These depend on page entry type, so compute them now. */ __field(bool, r) __field(bool, x) -__field (u8, u) + __field(signed char, u) ), TP_fast_assign(
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 129/388 KVM: nVMX: Hold KVMs srcu lock when syncing vmcs12->shadow
In reply to Greg Kroah-HartmanFrom: wanpeng li <[email protected]>
[ Upstream commit c9dfd3fb08352d439f0399b6fabe697681d2638c ]
For the duration of mapping eVMCS, it derefences ->memslots without holding ->srcu or ->slots_lock when accessing hv assist page. This patch fixes it by moving nested_sync_vmcs12_to_shadow to prepare_guest_switch, where the SRCU is already taken.
It can be reproduced by running kvm's evmcs_test selftest.
=============================
warning: suspicious rcu usage
5.6.0-rc1+ #53 tainted: g w ioe
-----------------------------
./include/linux/kvm_host.h:623 suspicious rcu_dereference_check() usage!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
1 lock held by evmcs_test/8507:
#0: ffff9ddd156d00d0 (&vcpu->mutex){+.+.}, at:
kvm_vcpu_ioctl+0x85/0x680 [kvm] stack backtrace: cpu: 6 pid: 8507 comm: evmcs_test tainted: g w ioe 5.6.0-rc1+ #53 hardware name: dell inc. optiplex 7040/0jctf8, bios 1.4.9 09/12/2016 call trace: dump_stack+0x68/0x9b kvm_read_guest_cached+0x11d/0x150 [kvm] kvm_hv_get_assist_page+0x33/0x40 [kvm] nested_enlightened_vmentry+0x2c/0x60 [kvm_intel] nested_vmx_handle_enlightened_vmptrld.part.52+0x32/0x1c0 [kvm_intel] nested_sync_vmcs12_to_shadow+0x439/0x680 [kvm_intel] vmx_vcpu_run+0x67a/0xe60 [kvm_intel] vcpu_enter_guest+0x35e/0x1bc0 [kvm] kvm_arch_vcpu_ioctl_run+0x40b/0x670 [kvm] kvm_vcpu_ioctl+0x370/0x680 [kvm] ksys_ioctl+0x235/0x850 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x77/0x780 entry_syscall_64_after_hwframe+0x49/0xbe
--- arch/x86/kvm/vmx/vmx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx/vmx.c +9 -2
@@ -1130,6 +1130,10 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu) vmx->guest_msrs[i].mask); } + +if (vmx->nested.need_vmcs12_to_shadow_sync) +nested_sync_vmcs12_to_shadow (vcpu); +if (vmx->guest_state_loaded)return ;
@@ -6486,8 +6490,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)vmcs_write32 (PLE_WINDOW , vmx->ple_window); } -if (vmx->nested.need_vmcs12_to_shadow_sync) -nested_sync_vmcs12_to_shadow (vcpu); +/* +* We did this in prepare_switch_to_guest, because it needs to +* be within srcu_read_lock. +*/ +WARN_ON_ONCE (vmx->nested.need_vmcs12_to_shadow_sync);if (test_bit (VCPU_REGS_RSP , (unsigned long *)&vcpu->arch.regs_dirty))vmcs_writel (GUEST_RSP , vcpu->arch.regs[VCPU_REGS_RSP ]);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 130/388 dmaengine: stm32-mdma: use vchan_terminate_vdesc() in .terminate_all
In reply to Greg Kroah-HartmanFrom: Amelie Delaunay <[email protected]>
[ Upstream commit dfc708812a2acfc0ca56f56233b3c3e7b0d4ffe7 ]
To avoid race with vchan_complete, use the race free way to terminate running transfer.
Move vdesc->node list_del in stm32_mdma_start_transfer instead of in stm32_mdma_xfer_end to avoid another race in vchan_dma_desc_free_list.
--- drivers/dma/stm32-mdma.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/dma/stm32-mdma.c +6 -3
@@ -1127,6 +1127,8 @@ static void stm32_mdma_start_transfer(struct stm32_mdma_chan *chan)return ; } +list_del (&vdesc->node); + chan->desc =to_stm32_mdma_desc (vdesc); hwdesc = chan->desc->node[0 ].hwdesc; chan->curr_hwdesc =0 ;
@@ -1242,8 +1244,10 @@ static int stm32_mdma_terminate_all(struct dma_chan *c)LIST_HEAD (head);spin_lock_irqsave (&chan->vchan.lock, flags); -if (chan->busy) { -stm32_mdma_stop (chan); +if (chan->desc) { +vchan_terminate_vdesc (&chan->desc->vdesc); +if (chan->busy) +stm32_mdma_stop (chan); chan->desc =NULL ; }vchan_get_all_descriptors (&chan->vchan, &head);
@@ -1331,7 +1335,6 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c,static void stm32_mdma_xfer_end (struct stm32_mdma_chan *chan) { -list_del (&chan->desc->vdesc.node);vchan_cookie_complete (&chan->desc->vdesc); chan->desc =NULL ; chan->busy = false;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 131/388 media: staging/imx: Missing assignment in imx_media_capture_device_register()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit ef0ed05dcef8a74178a8b480cce23a377b1de2b8 ]
There was supposed to be a "ret = " assignment here, otherwise the error handling on the next line won't work.
--- drivers/staging/media/imx/imx-media-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/media/imx/imx-media-capture.c +1 -1
@@ -785,7 +785,7 @@ int imx_media_capture_device_register(struct imx_media_video_dev *vdev)/* setup default format */ fmt_src.pad = priv->src_sd_pad; fmt_src.which =V4L2_SUBDEV_FORMAT_ACTIVE ; -v4l2_subdev_call (sd, pad, get_fmt,NULL , &fmt_src); + ret =v4l2_subdev_call (sd, pad, get_fmt,NULL , &fmt_src);if (ret) {v4l2_err (sd,"failed to get src_sd format\n" ); goto unreg;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 132/388 x86/pkeys: Add check for pkey "overflow"
In reply to Greg Kroah-HartmanFrom: Dave Hansen <[email protected]>
[ Upstream commit 16171bffc829272d5e6014bad48f680cb50943d9 ]
Alex Shi reported the pkey macros above arch_set_user_pkey_access() to be unused. They are unused, and even refer to a nonexistent CONFIG option.
But, they might have served a good use, which was to ensure that the code does not try to set values that would not fit in the PKRU register. As it stands, a too-large 'pkey' value would be likely to silently overflow the u32 new_pkru_bits.
Add a check to look for overflows. Also add a comment to remind any future developer to closely examine the types used to store pkey values if arch_max_pkey() ever changes.
This boots and passes the x86 pkey selftests.
--- arch/x86/include/asm/pkeys.h | 5 +++++ arch/x86/kernel/fpu/xstate.c | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-)
arch/x86/include/asm/pkeys.h +5 -0
@@ -4,6 +4,11 @@#define ARCH_DEFAULT_PKEY 0 +/* +* If more than 16 keys are ever supported, a thorough audit +* will be necessary to ensure that the types that store key +* numbers and masks have sufficient capacity. +*/ #define arch_max_pkey () (boot_cpu_has(X86_FEATURE_OSPKE) ? 16 : 1) extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
arch/x86/kernel/fpu/xstate.c +7 -2
@@ -895,8 +895,6 @@ const void *get_xsave_field_ptr(int xfeature_nr)#ifdef CONFIG_ARCH_HAS_PKEYS -#define NR_VALID_PKRU_BITS (CONFIG_NR_PROTECTION_KEYS * 2) -#define PKRU_VALID_MASK (NR_VALID_PKRU_BITS - 1)/* * This will go out and modify PKRU register to set the access * rights for @pkey to @init_val.
@@ -915,6 +913,13 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,if (!boot_cpu_has (X86_FEATURE_OSPKE ))return -EINVAL ; +/* +* This code should only be called with valid 'pkey' +* values originating from in-kernel users. Complain +* if a bad value is observed. +*/ +WARN_ON_ONCE (pkey >=arch_max_pkey ()); +/* Set the bits we need in PKRU: */ if (init_val &PKEY_DISABLE_ACCESS ) new_pkru_bits |=PKRU_AD_BIT ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 133/388 bpf: Remove recursion prevention from rcu free callback
In reply to Greg Kroah-HartmanFrom: Thomas Gleixner <[email protected]>
[ Upstream commit 8a37963c7ac9ecb7f86f8ebda020e3f8d6d7b8a0 ]
If an element is freed via RCU then recursion into BPF instrumentation functions is not a concern. The element is already detached from the map and the RCU callback does not hold any locks on which a kprobe, perf event or tracepoint attached BPF program could deadlock.
--- kernel/bpf/hashtab.c | 8 -------- 1 file changed, 8 deletions(-)
kernel/bpf/hashtab.c +0 -8
@@ -664,15 +664,7 @@ static void htab_elem_free_rcu(struct rcu_head *head) struct htab_elem *l = container_of(head, struct htab_elem, rcu);struct bpf_htab *htab = l->htab; -/* must increment bpf_prog_active to avoid kprobe+bpf triggering while -* we're calling kfree, otherwise deadlock is possible if kprobes -* are placed somewhere inside of slub -*/ -preempt_disable (); -__this_cpu_inc (bpf_prog_active);htab_elem_free (htab, l); -__this_cpu_dec (bpf_prog_active); -preempt_enable (); }static void htab_put_fd_value (struct bpf_htab *htab,struct htab_elem *l)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 134/388 dmaengine: stm32-dma: use vchan_terminate_vdesc() in .terminate_all
In reply to Greg Kroah-HartmanFrom: Amelie Delaunay <[email protected]>
[ Upstream commit d80cbef35bf89b763f06e03bb4ff8f933bf012c5 ]
To avoid race with vchan_complete, use the race free way to terminate running transfer.
Move vdesc->node list_del in stm32_dma_start_transfer instead of in stm32_mdma_chan_complete to avoid another race in vchan_dma_desc_free_list.
--- drivers/dma/stm32-dma.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/dma/stm32-dma.c +6 -3
@@ -488,8 +488,10 @@ static int stm32_dma_terminate_all(struct dma_chan *c)spin_lock_irqsave (&chan->vchan.lock, flags); -if (chan->busy) { -stm32_dma_stop (chan); +if (chan->desc) { +vchan_terminate_vdesc (&chan->desc->vdesc); +if (chan->busy) +stm32_dma_stop (chan); chan->desc =NULL ; }
@@ -545,6 +547,8 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan)if (!vdesc)return ; +list_del (&vdesc->node); + chan->desc =to_stm32_dma_desc (vdesc); chan->next_sg =0 ; }
@@ -622,7 +626,6 @@ static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan) }else { chan->busy = false;if (chan->next_sg == chan->desc->num_sgs) { -list_del (&chan->desc->vdesc.node);vchan_cookie_complete (&chan->desc->vdesc); chan->desc =NULL ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 135/388 dmaengine: tegra-apb: Prevent race conditions on channels freeing
In reply to Greg Kroah-HartmanFrom: Dmitry Osipenko <[email protected]>
[ Upstream commit 8e84172e372bdca20c305d92d51d33640d2da431 ]
It's incorrect to check the channel's "busy" state without taking a lock. That shouldn't cause any real troubles, nevertheless it's always better not to have any race conditions in the code.
--- drivers/dma/tegra20-apb-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/dma/tegra20-apb-dma.c +1 -2
@@ -1287,8 +1287,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)dev_dbg (tdc2dev (tdc),"Freeing channel %d\n" , tdc->id); -if (tdc->busy) -tegra_dma_terminate_all (dc); +tegra_dma_terminate_all (dc);spin_lock_irqsave (&tdc->lock, flags);list_splice_init (&tdc->pending_sg_req, &sg_req_list);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 136/388 soundwire: bus: disable pm_runtime in sdw_slave_delete
In reply to Greg Kroah-HartmanFrom: Pierre-Louis Bossart <[email protected]>
[ Upstream commit dff70572e9a3a1a01d9dbc2279faa784d95f41b6 ]
Before removing the slave device, disable pm_runtime to prevent any race condition with the resume being executed after the bus and slave devices are removed.
Since this pm_runtime_disable() is handled in common routines, implementations of Slave drivers do not need to call it in their .remove() routine.
--- drivers/soundwire/bus.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/soundwire/bus.c +2 -0
@@ -113,6 +113,8 @@ static int sdw_delete_slave(struct device *dev, void *data)struct sdw_slave *slave =dev_to_sdw_dev (dev);struct sdw_bus *bus = slave->bus; +pm_runtime_disable (dev); +sdw_slave_debugfs_exit (slave);mutex_lock (&bus->bus_lock);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 137/388 drm/amd/display: dal_ddc_i2c_payloads_create can fail causing panic
In reply to Greg Kroah-HartmanFrom: Aric Cyr <[email protected]>
[ Upstream commit 6a6c4a4d459ecacc9013c45dcbf2bc9747fdbdbd ]
[Why]
Since the i2c payload allocation can fail need to check return codes
[How]
Clean up i2c payload allocations and check for errors
--- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-)
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +25 -27
@@ -126,22 +126,16 @@ struct aux_payloads {struct vector payloads; }; -static struct i2c_payloads *dal_ddc_i2c_payloads_create (struct dc_context *ctx,uint32_t count) +static bool dal_ddc_i2c_payloads_create ( +struct dc_context *ctx, +struct i2c_payloads *payloads, +uint32_t count) { -struct i2c_payloads *payloads; - - payloads =kzalloc (sizeof (struct i2c_payloads ),GFP_KERNEL ); - -if (!payloads) -return NULL ; -if (dal_vector_construct ( &payloads->payloads, ctx, count,sizeof (struct i2c_payload ))) -return payloads; - -kfree (payloads); -return NULL ; +return true; +return false; }static struct i2c_payload *dal_ddc_i2c_payloads_get (struct i2c_payloads *p)
@@ -154,14 +148,12 @@ static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)return p->payloads.count; } -static void dal_ddc_i2c_payloads_destroy (struct i2c_payloads **p) +static void dal_ddc_i2c_payloads_destroy (struct i2c_payloads *p) { -if (!p || !*p) +if (!p)return ; -dal_vector_destruct (&(*p)->payloads); -kfree (*p); - *p =NULL ; +dal_vector_destruct (&p->payloads); }#define DDC_MIN (a, b) (((a) < (b)) ? (a) : (b))
@@ -521,9 +513,13 @@ bool dal_ddc_service_query_ddc_data(uint32_t payloads_num = write_payloads + read_payloads; +if (write_size >EDID_SEGMENT_SIZE || read_size >EDID_SEGMENT_SIZE )return false; +if (!payloads_num) +return false; +/*TODO: len of payload data for i2c and aux is uint8!!!!, * but we want to read 256 over i2c!!!!*/ if (dal_ddc_service_is_in_aux_transaction_mode (ddc)) {
@@ -556,23 +552,25 @@ bool dal_ddc_service_query_ddc_data( ret =dc_link_aux_transfer_with_retries (ddc, &read_payload); }else { -struct i2c_payloads *payloads = -dal_ddc_i2c_payloads_create (ddc->ctx, payloads_num); +struct i2c_command command = {0 }; +struct i2c_payloads payloads; + +if (!dal_ddc_i2c_payloads_create (ddc->ctx, &payloads, payloads_num)) +return false; -struct i2c_command command = { - .payloads =dal_ddc_i2c_payloads_get (payloads), - .number_of_payloads =0 , - .engine =DDC_I2C_COMMAND_ENGINE , - .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + command.payloads =dal_ddc_i2c_payloads_get (&payloads); + command.number_of_payloads =0 ; + command.engine =DDC_I2C_COMMAND_ENGINE ; + command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;dal_ddc_i2c_payloads_add ( - payloads, address, write_size, write_buf, true); + &payloads, address, write_size, write_buf, true);dal_ddc_i2c_payloads_add ( - payloads, address, read_size, read_buf, false); + &payloads, address, read_size, read_buf, false); command.number_of_payloads = -dal_ddc_i2c_payloads_get_count (payloads); +dal_ddc_i2c_payloads_get_count (&payloads); ret = dm_helpers_submit_i2c( ddc->ctx,
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 138/388 drm/omap: dss: Cleanup DSS ports on initialisation failure
In reply to Greg Kroah-HartmanFrom: Laurent Pinchart <[email protected]>
[ Upstream commit 2a0a3ae17d36fa86dcf7c8e8d7b7f056ebd6c064 ]
When the DSS initialises its output DPI and SDI ports, failures don't clean up previous successfully initialised ports. This can lead to resource leak or memory corruption. Fix it.
--- drivers/gpu/drm/omapdrm/dss/dss.c | 43 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-)
drivers/gpu/drm/omapdrm/dss/dss.c +26 -17
@@ -1151,46 +1151,38 @@ static const struct dss_features dra7xx_dss_feats = { .has_lcd_clk_src = true, }; -static int dss_init_ports (struct dss_device *dss) +static void __dss_uninit_ports (struct dss_device *dss,unsigned int num_ports) {struct platform_device *pdev = dss->pdev;struct device_node *parent = pdev->dev.of_node;struct device_node *port;unsigned int i; -int r; -for (i =0 ; i < dss->feat->num_ports; i++) { +for (i =0 ; i < num_ports; i++) { port =of_graph_get_port_by_id (parent, i);if (!port)continue ;switch (dss->feat->ports[i]) {case OMAP_DISPLAY_TYPE_DPI : - r =dpi_init_port (dss, pdev, port, dss->feat->model); -if (r) -return r; +dpi_uninit_port (port);break ; -case OMAP_DISPLAY_TYPE_SDI : - r =sdi_init_port (dss, pdev, port); -if (r) -return r; +sdi_uninit_port (port);break ; -default :break ; } } - -return 0 ; } -static void dss_uninit_ports (struct dss_device *dss) +static int dss_init_ports (struct dss_device *dss) {struct platform_device *pdev = dss->pdev;struct device_node *parent = pdev->dev.of_node;struct device_node *port; -int i; +unsigned int i; +int r;for (i =0 ; i < dss->feat->num_ports; i++) { port =of_graph_get_port_by_id (parent, i);
@@ -1199,15 +1191,32 @@ static void dss_uninit_ports(struct dss_device *dss)switch (dss->feat->ports[i]) {case OMAP_DISPLAY_TYPE_DPI : -dpi_uninit_port (port); + r =dpi_init_port (dss, pdev, port, dss->feat->model); +if (r) + goto error;break ; +case OMAP_DISPLAY_TYPE_SDI : -sdi_uninit_port (port); + r =sdi_init_port (dss, pdev, port); +if (r) + goto error;break ; +default :break ; } } + +return 0 ; + +error: +__dss_uninit_ports (dss, i); +return r; +} + +static void dss_uninit_ports (struct dss_device *dss) +{ +__dss_uninit_ports (dss, dss->feat->num_ports); }static int dss_video_pll_probe (struct dss_device *dss)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 139/388 iavf: use tc_cls_can_offload_and_chain0() instead of chain check
In reply to Greg Kroah-HartmanFrom: Jiri Pirko <[email protected]>
[ Upstream commit bb0858d8bc828ebc3eaa90be02a0f32bca3c2351 ]
Looks like the iavf code actually experienced a race condition, when a developer took code before the check for chain 0 was put to helper. So use tc_cls_can_offload_and_chain0() helper instead of direct check and move the check to _cb() so this is similar to i40e code.
--- drivers/net/ethernet/intel/iavf/iavf_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/intel/iavf/iavf_main.c +5 -3
@@ -3077,9 +3077,6 @@ static int iavf_delete_clsflower(struct iavf_adapter *adapter,static int iavf_setup_tc_cls_flower (struct iavf_adapter *adapter,struct flow_cls_offload *cls_flower) { -if (cls_flower->common.chain_index) -return -EOPNOTSUPP ; -switch (cls_flower->command) {case FLOW_CLS_REPLACE :return iavf_configure_clsflower (adapter, cls_flower);
@@ -3103,6 +3100,11 @@ static int iavf_setup_tc_cls_flower(struct iavf_adapter *adapter,static int iavf_setup_tc_block_cb (enum tc_setup_type type,void *type_data,void *cb_priv) { +struct iavf_adapter *adapter = cb_priv; + +if (!tc_cls_can_offload_and_chain0 (adapter->netdev, type_data)) +return -EOPNOTSUPP ; +switch (type) {case TC_SETUP_CLSFLOWER :return iavf_setup_tc_cls_flower (cb_priv, type_data);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 140/388 firmware: arm_sdei: Use cpus_read_lock() to avoid races with cpuhp
In reply to Greg Kroah-HartmanFrom: James Morse <[email protected]>
[ Upstream commit 54f529a6806c9710947a4f2cdc15d6ea54121ccd ]
SDEI has private events that need registering and enabling on each CPU. CPUs can come and go while we are trying to do this. SDEI tries to avoid these problems by setting the reregister flag before the register call, so any CPUs that come online register the event too. Sticking plaster like this doesn't work, as if the register call fails, a CPU that subsequently comes online will register the event before reregister is cleared.
Take cpus_read_lock() around the register and enable calls. We don't want surprise CPUs to do the wrong thing if they race with these calls failing.
--- drivers/firmware/arm_sdei.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
drivers/firmware/arm_sdei.c +14 -12
@@ -412,14 +412,19 @@ int sdei_event_enable(u32 event_num)return -ENOENT ; } -spin_lock (&sdei_list_lock); - event->reenable = true; -spin_unlock (&sdei_list_lock); +cpus_read_lock ();if (event->type ==SDEI_EVENT_TYPE_SHARED ) err =sdei_api_event_enable (event->event_num);else err =sdei_do_cross_call (_local_event_enable, event); + +if (!err) { +spin_lock (&sdei_list_lock); + event->reenable = true; +spin_unlock (&sdei_list_lock); + } +cpus_read_unlock ();mutex_unlock (&sdei_events_lock);return err;
@@ -621,21 +626,18 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg)break ; } -spin_lock (&sdei_list_lock); - event->reregister = true; -spin_unlock (&sdei_list_lock); - +cpus_read_lock (); err =_sdei_event_register (event);if (err) { -spin_lock (&sdei_list_lock); - event->reregister = false; - event->reenable = false; -spin_unlock (&sdei_list_lock); -sdei_event_destroy (event);pr_warn ("Failed to register event %u: %d\n" , event_num, err); + }else { +spin_lock (&sdei_list_lock); + event->reregister = true; +spin_unlock (&sdei_list_lock); } +cpus_read_unlock (); }while (0 );mutex_unlock (&sdei_events_lock);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 141/388 random: fix data races at timer_rand_state
In reply to Greg Kroah-HartmanFrom: Qian Cai <[email protected]>
[ Upstream commit e00d996a4317aff5351c4338dd97d390225412c2 ]
Fields in "struct timer_rand_state" could be accessed concurrently. Lockless plain reads and writes result in data races. Fix them by adding pairs of READ|WRITE_ONCE(). The data races were reported by KCSAN,
BUG: KCSAN: data-race in add_timer_randomness / add_timer_randomness
write to 0xffff9f320a0a01d0 of 8 bytes by interrupt on cpu 22:
add_timer_randomness+0x100/0x190 add_timer_randomness at drivers/char/random.c:1152 add_disk_randomness+0x85/0x280 scsi_end_request+0x43a/0x4a0 scsi_io_completion+0xb7/0x7e0 scsi_finish_command+0x1ed/0x2a0 scsi_softirq_done+0x1c9/0x1d0 blk_done_softirq+0x181/0x1d0 __do_softirq+0xd9/0x57c irq_exit+0xa2/0xc0 do_IRQ+0x8b/0x190 ret_from_intr+0x0/0x42 cpuidle_enter_state+0x15e/0x980 cpuidle_enter+0x69/0xc0 call_cpuidle+0x23/0x40 do_idle+0x248/0x280 cpu_startup_entry+0x1d/0x1f start_secondary+0x1b2/0x230 secondary_startup_64+0xb6/0xc0
no locks held by swapper/22/0.
irq event stamp: 32871382 _raw_spin_unlock_irqrestore+0x53/0x60 _raw_spin_lock_irqsave+0x21/0x60 _local_bh_enable+0x21/0x30 irq_exit+0xa2/0xc0
read to 0xffff9f320a0a01d0 of 8 bytes by interrupt on cpu 2:
add_timer_randomness+0xe8/0x190 add_disk_randomness+0x85/0x280 scsi_end_request+0x43a/0x4a0 scsi_io_completion+0xb7/0x7e0 scsi_finish_command+0x1ed/0x2a0 scsi_softirq_done+0x1c9/0x1d0 blk_done_softirq+0x181/0x1d0 __do_softirq+0xd9/0x57c irq_exit+0xa2/0xc0 do_IRQ+0x8b/0x190 ret_from_intr+0x0/0x42 cpuidle_enter_state+0x15e/0x980 cpuidle_enter+0x69/0xc0 call_cpuidle+0x23/0x40 do_idle+0x248/0x280 cpu_startup_entry+0x1d/0x1f start_secondary+0x1b2/0x230 secondary_startup_64+0xb6/0xc0
no locks held by swapper/2/0.
irq event stamp: 37846304 _raw_spin_unlock_irqrestore+0x53/0x60 _raw_spin_lock_irqsave+0x21/0x60 _local_bh_enable+0x21/0x30 irq_exit+0xa2/0xc0
Reported by Kernel Concurrency Sanitizer on:
Hardware name: HP ProLiant BL660c Gen9, BIOS I38 10/17/2018
--- drivers/char/random.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/char/random.c +6 -6
@@ -1223,14 +1223,14 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)* We take into account the first, second and third-order deltas * in order to make our estimate. */ - delta = sample.jiffies - state->last_time; - state->last_time = sample.jiffies; + delta = sample.jiffies -READ_ONCE (state->last_time); +WRITE_ONCE (state->last_time, sample.jiffies); - delta2 = delta - state->last_delta; - state->last_delta = delta; + delta2 = delta -READ_ONCE (state->last_delta); +WRITE_ONCE (state->last_delta, delta); - delta3 = delta2 - state->last_delta2; - state->last_delta2 = delta2; + delta3 = delta2 -READ_ONCE (state->last_delta2); +WRITE_ONCE (state->last_delta2, delta2);if (delta <0 ) delta = -delta;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 142/388 bus: hisi_lpc: Fixup IO ports addresses to avoid use-after-free in host removal
In reply to Greg Kroah-HartmanFrom: John Garry <[email protected]>
[ Upstream commit a6dd255bdd7d00bbdbf78ba00bde9fc64f86c3a7 ]
Some released ACPI FW for Huawei boards describes incorrect the port IO address range for child devices, in that it tells us the IO port max range is 0x3fff for each child device, which is not correct. The address range should be [e4:e8) or similar. With this incorrect upper range, the child device IO port resources overlap.
As such, the kernel thinks that the LPC host serial device is a child of the IPMI device:
root@(none)$ more /proc/ioports
[...]
00ffc0e3-00ffffff : hisi-lpc-ipmi.0.auto
00ffc0e3-00ffc0e3 : ipmi_si
00ffc0e4-00ffc0e4 : ipmi_si
00ffc0e5-00ffc0e5 : ipmi_si
00ffc2f7-00ffffff : serial8250.1.auto
00ffc2f7-00ffc2fe : serial
root@(none)$They should both be siblings. Note that these are logical PIO addresses, which have a direct mapping from the FW IO port ranges.
This shows up as a real issue when we enable CONFIG_KASAN and CONFIG_DEBUG_TEST_DRIVER_REMOVE - we see use-after-free warnings in the host removal path:
==================================================================
BUG: KASAN: use-after-free in release_resource+0x38/0xc8 Read of size 8 at addr ffff0026accdbc38 by task swapper/0/1 CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.5.0-rc6-00001-g68e186e77b5c-dirty #1593 Hardware name: Huawei Taishan 2180 /D03, BIOS Hisilicon D03 IT20 Nemo 2.0 RC0 03/30/2018 Call trace: dump_backtrace+0x0/0x290 show_stack+0x14/0x20 dump_stack+0xf0/0x14c print_address_description.isra.9+0x6c/0x3b8 __kasan_report+0x12c/0x23c kasan_report+0xc/0x18 __asan_load8+0x94/0xb8 release_resource+0x38/0xc8 platform_device_del.part.10+0x80/0xe0 platform_device_unregister+0x20/0x38 hisi_lpc_acpi_remove_subdev+0x10/0x20 device_for_each_child+0xc8/0x128 hisi_lpc_acpi_remove+0x4c/0xa8 hisi_lpc_remove+0xbc/0xc0 platform_drv_remove+0x3c/0x68 really_probe+0x174/0x548 driver_probe_device+0x7c/0x148 device_driver_attach+0x94/0xa0 __driver_attach+0xa4/0x110 bus_for_each_dev+0xe8/0x158 driver_attach+0x30/0x40 bus_add_driver+0x234/0x2f0 driver_register+0xbc/0x1d0 __platform_driver_register+0x7c/0x88 hisi_lpc_driver_init+0x18/0x20 do_one_initcall+0xb4/0x258 kernel_init_freeable+0x248/0x2c0 kernel_init+0x10/0x118 ret_from_fork+0x10/0x1c
...
The issue here is that the kernel created an incorrect parent-child resource dependency between two devices, and references the false parent node when deleting the second child device, when it had been deleted already.
Fix up the child device resources from FW to create proper IO port resource relationships for broken FW.
With this, the IO port layout looks more healthy:
root@(none)$ more /proc/ioports [...] 00ffc0e3-00ffc0e7 : hisi-lpc-ipmi.0.auto 00ffc0e3-00ffc0e3 : ipmi_si 00ffc0e4-00ffc0e4 : ipmi_si 00ffc0e5-00ffc0e5 : ipmi_si 00ffc2f7-00ffc2ff : serial8250.1.auto 00ffc2f7-00ffc2fe : serial
--- drivers/bus/hisi_lpc.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-)
drivers/bus/hisi_lpc.c +25 -2
@@ -358,6 +358,26 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,return 0 ; } +/* +* Released firmware describes the IO port max address as 0x3fff, which is +* the max host bus address. Fixup to a proper range. This will probably +* never be fixed in firmware. +*/ +static void hisi_lpc_acpi_fixup_child_resource (struct device *hostdev, +struct resource *r) +{ +if (r->end !=0x3fff ) +return ; + +if (r->start ==0xe4 ) + r->end =0xe4 +0x04 -1 ; +else if (r->start ==0x2f8 ) + r->end =0x2f8 +0x08 -1 ; +else +dev_warn (hostdev,"unrecognised resource %pR to fixup, ignoring\n" , + r); +} +/* * hisi_lpc_acpi_set_io_res - set the resources for a child * @child: the device node to be updated the I/O resource
@@ -419,8 +439,11 @@ static int hisi_lpc_acpi_set_io_res(struct device *child,return -ENOMEM ; } count =0 ; -list_for_each_entry (rentry, &resource_list, node) - resources[count++] = *rentry->res; +list_for_each_entry (rentry, &resource_list, node) { + resources[count] = *rentry->res; +hisi_lpc_acpi_fixup_child_resource (hostdev, &resources[count]); + count++; + }acpi_dev_free_resource_list (&resource_list);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 143/388 ASoC: SOF: ipc: check ipc return value before data copy
In reply to Greg Kroah-HartmanFrom: Jaska Uimonen <[email protected]>
[ Upstream commit 1919b42ca4ad75a2397081164661af3ce5a7b8f4 ]
In tx_wait_done the ipc payload is copied before the DSP transaction error code is checked. This might lead to corrupted data in kernel side even though the error would be handled later. It is also pointless to copy the data in case of error. So change the order of error check and copy.
--- sound/soc/sof/ipc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
sound/soc/sof/ipc.c +7 -5
@@ -215,15 +215,17 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg,snd_sof_trace_notify_for_error (ipc->sdev); ret = -ETIMEDOUT ; }else { -/* copy the data returned from DSP */ ret = msg->reply_error; -if (msg->reply_size) -memcpy (reply_data, msg->reply_data, msg->reply_size); -if (ret <0 ) +if (ret <0 ) {dev_err (sdev->dev,"error: ipc error for 0x%x size %zu\n" , hdr->cmd, msg->reply_size); -else + }else {ipc_log_header (sdev->dev,"ipc tx succeeded" , hdr->cmd); +if (msg->reply_size) +/* copy the data returned from DSP */ +memcpy (reply_data, msg->reply_data, + msg->reply_size); + } }return ret;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 144/388 media: go7007: Fix URB type for interrupt handling
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
[ Upstream commit a3ea410cac41b19a5490aad7fe6d9a9a772e646e ]
Josef reported that his old-and-good Plextor ConvertX M402U video converter spews lots of WARNINGs on the recent kernels, and it turned out that the device uses a bulk endpoint for interrupt handling just like 2250 board.
For fixing it, generalize the check with the proper verification of the endpoint instead of hard-coded board type check.
--- drivers/media/usb/go7007/go7007-usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/usb/go7007/go7007-usb.c +3 -1
@@ -1044,6 +1044,7 @@ static int go7007_usb_probe(struct usb_interface *intf,struct go7007_usb *usb;const struct go7007_usb_board *board;struct usb_device *usbdev =interface_to_usbdev (intf); +struct usb_host_endpoint *ep;unsigned num_i2c_devs;char *name;int video_pipe, i, v_urb_len;
@@ -1140,7 +1141,8 @@ static int go7007_usb_probe(struct usb_interface *intf,if (usb->intr_urb->transfer_buffer ==NULL ) goto allocfail; -if (go->board_id ==GO7007_BOARDID_SENSORAY_2250 ) + ep = usb->usbdev->ep_in[4 ]; +if (usb_endpoint_type (&ep->desc) ==USB_ENDPOINT_XFER_BULK ) usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, usb_rcvbulkpipe(usb->usbdev, 4), usb->intr_urb->transfer_buffer, 2*sizeof(u16),
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 145/388 Bluetooth: guard against controllers sending zerod events
In reply to Greg Kroah-HartmanFrom: Alain Michaud <[email protected]>
[ Upstream commit 08bb4da90150e2a225f35e0f642cdc463958d696 ]
Some controllers have been observed to send zero'd events under some conditions. This change guards against this condition as well as adding a trace to facilitate diagnosability of this condition.
--- net/bluetooth/hci_event.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/bluetooth/hci_event.c +6 -0
@@ -5853,6 +5853,11 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)u8 status =0 , event = hdr->evt, req_evt =0 ;u16 opcode =HCI_OP_NOP ; +if (!event) { +bt_dev_warn (hdev,"Received unexpected HCI Event 00000000" ); + goto done; + } +if (hdev->sent_cmd &&bt_cb (hdev->sent_cmd)->hci.req_event == event) {struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; opcode =__le16_to_cpu (cmd_hdr->opcode);
@@ -6064,6 +6069,7 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)req_complete_skb (hdev, status, opcode, orig_skb); } +done:kfree_skb (orig_skb);kfree_skb (skb); hdev->stat.evt_rx++;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 146/388 timekeeping: Prevent 32bit truncation in scale64_check_overflow()
In reply to Greg Kroah-HartmanFrom: Wen Yang <[email protected]>
[ Upstream commit 4cbbc3a0eeed675449b1a4d080008927121f3da3 ]
While unlikely the divisor in scale64_check_overflow() could be >= 32bit in scale64_check_overflow(). do_div() truncates the divisor to 32bit at least on 32bit platforms.
Use div64_u64() instead to avoid the truncation to 32-bit.
[ tglx: Massaged changelog ]
--- kernel/time/timekeeping.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/time/timekeeping.c +1 -2
@@ -1005,9 +1005,8 @@ static int scale64_check_overflow(u64 mult, u64 div, u64 *base) ((int)sizeof(u64)*8 - fls64(mult) < fls64(rem))) return -EOVERFLOW; tmp *= mult; - rem *= mult; -do_div (rem, div); + rem =div64_u64 (rem * mult, div); *base = tmp + rem;return 0 ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 147/388 powerpc/book3s64: Fix error handling in mm_iommu_do_alloc()
In reply to Greg Kroah-HartmanFrom: Alexey Kardashevskiy <[email protected]>
[ Upstream commit c4b78169e3667413184c9a20e11b5832288a109f ]
The last jump to free_exit in mm_iommu_do_alloc() happens after page pointers in struct mm_iommu_table_group_mem_t were already converted to physical addresses. Thus calling put_page() on these physical addresses will likely crash.
This moves the loop which calculates the pageshift and converts page struct pointers to physical addresses later after the point when we cannot fail; thus eliminating the need to convert pointers back.
--- arch/powerpc/mm/book3s64/iommu_api.c | 39 +++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-)
arch/powerpc/mm/book3s64/iommu_api.c +21 -18
@@ -121,24 +121,6 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua, goto free_exit; } - pageshift =PAGE_SHIFT ; -for (i =0 ; i < entries; ++i) { -struct page *page = mem->hpages[i]; - -/* -* Allow to use larger than 64k IOMMU pages. Only do that -* if we are backed by hugetlb. -*/ -if ((mem->pageshift >PAGE_SHIFT ) &&PageHuge (page)) - pageshift =page_shift (compound_head (page)); - mem->pageshift =min (mem->pageshift, pageshift); -/* -* We don't need struct page reference any more, switch -* to physical address. -*/ - mem->hpas[i] =page_to_pfn (page) <<PAGE_SHIFT ; - } - good_exit:atomic64_set (&mem->mapped,1 ); mem->used =1 ;
@@ -158,6 +140,27 @@ good_exit: } } +if (mem->dev_hpa ==MM_IOMMU_TABLE_INVALID_HPA ) { +/* +* Allow to use larger than 64k IOMMU pages. Only do that +* if we are backed by hugetlb. Skip device memory as it is not +* backed with page structs. +*/ + pageshift =PAGE_SHIFT ; +for (i =0 ; i < entries; ++i) { +struct page *page = mem->hpages[i]; + +if ((mem->pageshift >PAGE_SHIFT ) &&PageHuge (page)) + pageshift =page_shift (compound_head (page)); + mem->pageshift =min (mem->pageshift, pageshift); +/* +* We don't need struct page reference any more, switch +* to physical address. +*/ + mem->hpas[i] =page_to_pfn (page) <<PAGE_SHIFT ; + } + } +list_add_rcu (&mem->next, &mm->context.iommu_group_mem_list);mutex_unlock (&mem_list_mutex);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 148/388 drm/amd/display: fix image corruption with ODM 2:1 DSC 2 slice
In reply to Greg Kroah-HartmanFrom: Wenjing Liu <[email protected]>
[ Upstream commit df8e34ac27e8a0d8dce364628226c5619693c3fd ]
[why]
When combining two or more pipes in DSC mode, there will always be more than 1 slice per line. In this case, as per DSC rules, the sink device is expecting that the ICH is reset at the end of each slice line (i.e. ICH_RESET_AT_END_OF_LINE must be configured based on the number of slices at the output of ODM). It is recommended that software set ICH_RESET_AT_END_OF_LINE = 0xF for each DSC in the ODM combine. However the current code only set ICH_RESET_AT_END_OF_LINE = 0xF when number of slice per DSC engine is greater than 1 instead of number of slice per output after ODM combine.
[how]
Add is_odm in dsc config. Set ICH_RESET_AT_END_OF_LINE = 0xF if either is_odm or number of slice per DSC engine is greater than 1.
--- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h | 1 + 4 files changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +2 -0
@@ -400,6 +400,7 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;ASSERT (dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt ==0 ); dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
@@ -504,6 +505,7 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;DC_LOG_DSC (" " );
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c +1 -1
@@ -351,6 +351,7 @@ static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_ dsc_reg_vals->pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable; dsc_reg_vals->pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth; dsc_reg_vals->alternate_ich_encoding_en = dsc_reg_vals->pps.dsc_version_minor ==1 ?0 :1 ; + dsc_reg_vals->ich_reset_at_eol = (dsc_cfg->is_odm || dsc_reg_vals->num_slices_h >1 ) ?0xF :0 ;// TODO: in addition to validating slice height (pic height must be divisible by slice height), // see what happens when the same condition doesn't apply for slice_width/pic_width.
@@ -513,7 +514,6 @@ static void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, cons reg_vals->pps.rc_buf_thresh[i] = reg_vals->pps.rc_buf_thresh[i] >>6 ; reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size; - reg_vals->ich_reset_at_eol = reg_vals->num_slices_h ==1 ?0 :0xf ; }static void dsc_write_to_registers (struct display_stream_compressor *dsc,const struct dsc_reg_values *reg_vals)
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +1 -0
@@ -2275,6 +2275,7 @@ static bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx) + stream->timing.v_border_bottom; dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +1 -0
@@ -36,6 +36,7 @@ struct dsc_config {uint32_t pic_height;enum dc_pixel_encoding pixel_encoding;enum dc_color_depth color_depth;/* Bits per component */ +bool is_odm;struct dc_dsc_config dc_dsc_cfg; };
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 149/388 ext4: fix a data race at inode->i_disksize
In reply to Greg Kroah-HartmanFrom: Qiujun Huang <[email protected]>
[ Upstream commit dce8e237100f60c28cc66effb526ba65a01d8cb3 ]
KCSAN find inode->i_disksize could be accessed concurrently.
BUG: KCSAN: data-race in ext4_mark_iloc_dirty / ext4_write_end
write (marked) to 0xffff8b8932f40090 of 8 bytes by task 66792 on cpu 0:
ext4_write_end+0x53f/0x5b0 ext4_da_write_end+0x237/0x510 generic_perform_write+0x1c4/0x2a0 ext4_buffered_write_iter+0x13a/0x210 ext4_file_write_iter+0xe2/0x9b0 new_sync_write+0x29c/0x3a0 __vfs_write+0x92/0xa0 vfs_write+0xfc/0x2a0 ksys_write+0xe8/0x140 __x64_sys_write+0x4c/0x60 do_syscall_64+0x8a/0x2a0 entry_SYSCALL_64_after_hwframe+0x44/0xa9
read to 0xffff8b8932f40090 of 8 bytes by task 14414 on cpu 1:
ext4_mark_iloc_dirty+0x716/0x1190 ext4_mark_inode_dirty+0xc9/0x360 ext4_convert_unwritten_extents+0x1bc/0x2a0 ext4_convert_unwritten_io_end_vec+0xc5/0x150 ext4_put_io_end+0x82/0x130 ext4_writepages+0xae7/0x16f0 do_writepages+0x64/0x120 __writeback_single_inode+0x7d/0x650 writeback_sb_inodes+0x3a4/0x860 __writeback_inodes_wb+0xc4/0x150 wb_writeback+0x43f/0x510 wb_workfn+0x3b2/0x8a0 process_one_work+0x39b/0x7e0 worker_thread+0x88/0x650 kthread+0x1d4/0x1f0 ret_from_fork+0x35/0x40
The plain read is outside of inode->i_data_sem critical section which results in a data race. Fix it by adding READ_ONCE().
--- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/inode.c +1 -1
@@ -5315,7 +5315,7 @@ static int ext4_do_update_inode(handle_t *handle, raw_inode->i_file_acl_high =cpu_to_le16 (ei->i_file_acl >>32 ); raw_inode->i_file_acl_lo =cpu_to_le32 (ei->i_file_acl); -if (ei->i_disksize !=ext4_isize (inode->i_sb, raw_inode)) { +if (READ_ONCE (ei->i_disksize) !=ext4_isize (inode->i_sb, raw_inode)) {ext4_isize_set (raw_inode, ei->i_disksize); need_datasync =1 ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 150/388 perf jevents: Fix leak of mapfile memory
In reply to Greg Kroah-HartmanFrom: John Garry <[email protected]>
[ Upstream commit 3f5777fbaf04c58d940526a22a2e0c813c837936 ]
The memory for global pointer is never freed during normal program execution, so let's do that in the main function exit as a good programming practice.
A stray blank line is also removed.
--- tools/perf/pmu-events/jevents.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
tools/perf/pmu-events/jevents.c +9 -6
@@ -1068,10 +1068,9 @@ static int process_one_file(const char *fpath, const struct stat *sb,*/ int main (int argc,char *argv[]) { -int rc; +int rc, ret =0 ;int maxfds;char ldirname[PATH_MAX ]; -const char *arch;const char *output_file;const char *start_dirname;
@@ -1142,7 +1141,8 @@ int main(int argc, char *argv[])/* Make build fail */ fclose (eventsfp);free_arch_std_events (); -return 1 ; + ret =1 ; + goto out_free_mapfile; }else if (rc) { goto empty_map; }
@@ -1160,14 +1160,17 @@ int main(int argc, char *argv[])/* Make build fail */ fclose (eventsfp);free_arch_std_events (); -return 1 ; + ret =1 ; } -return 0 ; + + goto out_free_mapfile; empty_map:fclose (eventsfp);create_empty_mapping (output_file);free_arch_std_events (); -return 0 ; +out_free_mapfile: +free (mapfile); +return ret; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 151/388 mm: avoid data corruption on CoW fault into PFN-mapped VMA
In reply to Greg Kroah-HartmanFrom: Kirill A. Shutemov <[email protected]>
[ Upstream commit c3e5ea6ee574ae5e845a40ac8198de1fb63bb3ab ]
Jeff Moyer has reported that one of xfstests triggers a warning when run on DAX-enabled filesystem:
WARNING: CPU: 76 PID: 51024 at mm/memory.c:2317 wp_page_copy+0xc40/0xd50 ... wp_page_copy+0x98c/0xd50 (unreliable) do_wp_page+0xd8/0xad0 __handle_mm_fault+0x748/0x1b90 handle_mm_fault+0x120/0x1f0 __do_page_fault+0x240/0xd70 do_page_fault+0x38/0xd0 handle_page_fault+0x10/0x30
The warning happens on failed __copy_from_user_inatomic() which tries to copy data into a CoW page.
This happens because of race between MADV_DONTNEED and CoW page fault:
CPU0 CPU1
handle_mm_fault()
do_wp_page()
wp_page_copy()
do_wp_page()
madvise(MADV_DONTNEED)
zap_page_range()
zap_pte_range()
ptep_get_and_clear_full()
<TLB flush>
__copy_from_user_inatomic()
sees empty PTE and fails
WARN_ON_ONCE(1)
clear_page()The solution is to re-try __copy_from_user_inatomic() under PTL after checking that PTE is matches the orig_pte.
The second copy attempt can still fail, like due to non-readable PTE, but there's nothing reasonable we can do about, except clearing the CoW page.
--- mm/memory.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-)
mm/memory.c +27 -8
@@ -2163,7 +2163,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src,bool ret;void *kaddr;void __user *uaddr; -bool force_mkyoung; +bool locked = false;struct vm_area_struct *vma = vmf->vma;struct mm_struct *mm = vma->vm_mm;unsigned long addr = vmf->address;
@@ -2188,11 +2188,11 @@ static inline bool cow_user_page(struct page *dst, struct page *src,* On architectures with software "accessed" bits, we would * take a double page fault, so mark it accessed here. */ - force_mkyoung =arch_faults_on_old_pte () && !pte_young (vmf->orig_pte); -if (force_mkyoung) { +if (arch_faults_on_old_pte () && !pte_young (vmf->orig_pte)) {pte_t entry; vmf->pte =pte_offset_map_lock (mm, vmf->pmd, addr, &vmf->ptl); + locked = true;if (!likely (pte_same (*vmf->pte, vmf->orig_pte))) {/* * Other thread has already handled the fault
@@ -2216,18 +2216,37 @@ static inline bool cow_user_page(struct page *dst, struct page *src,* zeroes. */ if (__copy_from_user_inatomic (kaddr, uaddr,PAGE_SIZE )) { +if (locked) + goto warn; + +/* Re-validate under PTL if the page is still mapped */ + vmf->pte =pte_offset_map_lock (mm, vmf->pmd, addr, &vmf->ptl); + locked = true; +if (!likely (pte_same (*vmf->pte, vmf->orig_pte))) { +/* The PTE changed under us. Retry page fault. */ + ret = false; + goto pte_unlock; + } +/* -* Give a warn in case there can be some obscure -* use-case +* The same page can be mapped back since last copy attampt. +* Try to copy again under PTL. */ -WARN_ON_ONCE (1 ); -clear_page (kaddr); +if (__copy_from_user_inatomic (kaddr, uaddr,PAGE_SIZE )) { +/* +* Give a warn in case there can be some obscure +* use-case +*/ +warn: +WARN_ON_ONCE (1 ); +clear_page (kaddr); + } } ret = true; pte_unlock: -if (force_mkyoung) +if (locked)pte_unmap_unlock (vmf->pte, vmf->ptl);kunmap_atomic (kaddr);flush_dcache_page (dst);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 152/388 drm/amdgpu: increase atombios cmd timeout
In reply to Greg Kroah-HartmanFrom: John Clements <[email protected]>
[ Upstream commit 1b3460a8b19688ad3033b75237d40fa580a5a953 ]
mitigates race condition on BACO reset between GPU bootcode and driver reload
--- drivers/gpu/drm/amd/amdgpu/atom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/atom.c +2 -2
@@ -744,8 +744,8 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) cjiffies = jiffies;if (time_after (cjiffies, ctx->last_jump_jiffies)) { cjiffies -= ctx->last_jump_jiffies; -if ((jiffies_to_msecs (cjiffies) >5000 )) { -DRM_ERROR ("atombios stuck in loop for more than 5secs aborting\n" ); +if ((jiffies_to_msecs (cjiffies) >10000 )) { +DRM_ERROR ("atombios stuck in loop for more than 10secs aborting\n" ); ctx->abort = true; } }else {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 153/388 ARM: OMAP2+: Handle errors for cpu_pm
In reply to Greg Kroah-HartmanFrom: Tony Lindgren <[email protected]>
[ Upstream commit 55be2f50336f67800513b46c5ba6270e4ed0e784 ]
We need to check for errors when calling cpu_pm_enter() and cpu_cluster_pm_enter(). And we need to bail out on errors as otherwise we can enter a deeper idle state when not desired.
I'm not aware of the lack of error handling causing issues yet, but we need this at least for blocking deeper idle states when a GPIO instance has pending interrupts.
--- arch/arm/mach-omap2/cpuidle34xx.c | 9 +++++++-- arch/arm/mach-omap2/cpuidle44xx.c | 26 +++++++++++++++++--------- arch/arm/mach-omap2/pm34xx.c | 8 ++++++-- 3 files changed, 30 insertions(+), 13 deletions(-)
arch/arm/mach-omap2/cpuidle34xx.c +7 -2
@@ -109,6 +109,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) {struct omap3_idle_statedata *cx = &omap3_idle_data[index]; +int error;if (omap_irq_pending () ||need_resched ()) goto return_sleep_time;
@@ -125,8 +126,11 @@ static int omap3_enter_idle(struct cpuidle_device *dev,* Call idle CPU PM enter notifier chain so that * VFP context is saved. */ -if (cx->mpu_state ==PWRDM_POWER_OFF ) -cpu_pm_enter (); +if (cx->mpu_state ==PWRDM_POWER_OFF ) { + error =cpu_pm_enter (); +if (error) + goto out_clkdm_set; + }/* Execute ARM wfi */ omap_sram_idle ();
@@ -139,6 +143,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)cpu_pm_exit (); +out_clkdm_set:/* Re-allow idle for C1 */ if (cx->flags &OMAP_CPUIDLE_CX_NO_CLKDM_IDLE )clkdm_allow_idle (mpu_pd->pwrdm_clkdms[0 ]);
arch/arm/mach-omap2/cpuidle44xx.c +17 -9
@@ -122,6 +122,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, {struct idle_statedata *cx = state_ptr + index;u32 mpuss_can_lose_context =0 ; +int error;/* * CPU0 has to wait and stay ON until CPU1 is OFF state.
@@ -159,7 +160,9 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,* Call idle CPU PM enter notifier chain so that * VFP and per CPU interrupt context is saved. */ -cpu_pm_enter (); + error =cpu_pm_enter (); +if (error) + goto cpu_pm_out;if (dev->cpu ==0 ) {pwrdm_set_logic_retst (mpu_pd, cx->mpu_logic_state);
@@ -169,13 +172,17 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,* Call idle CPU cluster PM enter notifier chain * to save GIC and wakeupgen context. */ -if (mpuss_can_lose_context) -cpu_cluster_pm_enter (); +if (mpuss_can_lose_context) { + error =cpu_cluster_pm_enter (); +if (error) + goto cpu_cluster_pm_out; + } }omap4_enter_lowpower (dev->cpu, cx->cpu_state); cpu_done[dev->cpu] = true; +cpu_cluster_pm_out:/* Wakeup CPU1 only if it is not offlined */ if (dev->cpu ==0 &&cpumask_test_cpu (1 , cpu_online_mask)) {
@@ -197,12 +204,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, } } -/* -* Call idle CPU PM exit notifier chain to restore -* VFP and per CPU IRQ context. -*/ -cpu_pm_exit (); -/* * Call idle CPU cluster PM exit notifier chain * to restore GIC and wakeupgen context.
@@ -210,6 +211,13 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,if (dev->cpu ==0 && mpuss_can_lose_context)cpu_cluster_pm_exit (); +/* +* Call idle CPU PM exit notifier chain to restore +* VFP and per CPU IRQ context. +*/ +cpu_pm_exit (); + +cpu_pm_out:tick_broadcast_exit (); fail:
arch/arm/mach-omap2/pm34xx.c +6 -2
@@ -194,6 +194,7 @@ void omap_sram_idle(void)int per_next_state =PWRDM_POWER_ON ;int core_next_state =PWRDM_POWER_ON ;u32 sdrc_pwr =0 ; +int error; mpu_next_state =pwrdm_read_next_pwrst (mpu_pwrdm);switch (mpu_next_state) {
@@ -222,8 +223,11 @@ void omap_sram_idle(void)pwrdm_pre_transition (NULL );/* PER */ -if (per_next_state ==PWRDM_POWER_OFF ) -cpu_cluster_pm_enter (); +if (per_next_state ==PWRDM_POWER_OFF ) { + error =cpu_cluster_pm_enter (); +if (error) +return ; + }/* CORE */ if (core_next_state <PWRDM_POWER_ON ) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 154/388 drm/amd/display: Stop if retimer is not available
In reply to Greg Kroah-HartmanFrom: Rodrigo Siqueira <[email protected]>
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in order to make it work well, all settings required for this configuration are loaded from the Atom bios which include the i2c address. If the retimer feature is not available, we should abort the attempt to set this feature, otherwise, it makes the following line return I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven, and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998 write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64 crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F GAMING, BIOS 2605 08/06/2019 RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7 c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42 0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP: 0018:ffffa99d02726fd0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006 RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440 RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600 R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000 FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0 Call Trace: core_link_enable_stream+0x626/0x680 [amdgpu] dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu] dc_commit_state+0x331/0x5e0 [amdgpu] ? drm_calc_timestamping_constants+0xf9/0x150 [drm] amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu] ? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu] commit_tail+0x42/0x70 [drm_kms_helper] drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper] amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu] drm_atomic_commit+0x4a/0x50 [drm] restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper] restore_fbdev_mode+0x4c/0x160 [drm_kms_helper] ? _cond_resched+0x19/0x40 drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper] drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper] fbcon_init+0x471/0x630 visual_init+0xd5/0x130 do_bind_con_driver+0x20a/0x430 do_take_over_console+0x7d/0x1b0 do_fbcon_takeover+0x5c/0xb0 fbcon_event_notify+0x6cd/0x8a0 notifier_call_chain+0x4c/0x70 blocking_notifier_call_chain+0x43/0x60 fb_notifier_call_chain+0x1b/0x20 register_framebuffer+0x254/0x360 __drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper] drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper] amdgpu_fbdev_init+0xcd/0x100 [amdgpu] amdgpu_device_init+0x1156/0x1930 [amdgpu] amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu] drm_dev_register+0x12b/0x1c0 [drm] amdgpu_pci_probe+0xd3/0x160 [amdgpu] local_pci_probe+0x47/0xa0 pci_device_probe+0x142/0x1b0 really_probe+0xf5/0x3d0 driver_probe_device+0x11b/0x130 device_driver_attach+0x58/0x60 __driver_attach+0xa3/0x140 ? device_driver_attach+0x60/0x60 ? device_driver_attach+0x60/0x60 bus_for_each_dev+0x74/0xb0 ? kmem_cache_alloc_trace+0x1a3/0x1c0 driver_attach+0x1e/0x20 bus_add_driver+0x147/0x220 ? 0xffffffffc0cb9000 driver_register+0x60/0x100 ? 0xffffffffc0cb9000 __pci_register_driver+0x5a/0x60 amdgpu_init+0x74/0x83 [amdgpu] do_one_initcall+0x4a/0x1fa ? _cond_resched+0x19/0x40 ? kmem_cache_alloc_trace+0x3f/0x1c0 ? __vunmap+0x1cc/0x200 do_init_module+0x5f/0x227 load_module+0x2330/0x2b40 __do_sys_finit_module+0xfc/0x120 ? __do_sys_finit_module+0xfc/0x120 __x64_sys_finit_module+0x1a/0x20 do_syscall_64+0x5a/0x130 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f14f9500839 Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the way that we abort this configuration if the feature is not available in the device. For debug sake, we kept a simple log message in case the retimer is not available.
--- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 67 ++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-)
drivers/gpu/drm/amd/display/dc/core/dc_link.c +29 -38
@@ -1733,8 +1733,7 @@ static void write_i2c_retimer_setting( slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A * needs to be set to 1 on every 0xA-0xC write.
@@ -1752,8 +1751,7 @@ static void write_i2c_retimer_setting( pipe_ctx->stream->link->ddc, slave_address, &offset, 1, &value, 1);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail; } buffer[0 ] = offset;
@@ -1765,8 +1763,7 @@ static void write_i2c_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail; } } }
@@ -1786,8 +1783,7 @@ static void write_i2c_retimer_setting( slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A * needs to be set to 1 on every 0xA-0xC write.
@@ -1805,8 +1801,7 @@ static void write_i2c_retimer_setting( pipe_ctx->stream->link->ddc, slave_address, &offset, 1, &value, 1);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail; } buffer[0 ] = offset;
@@ -1818,8 +1813,7 @@ static void write_i2c_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail; } } }
@@ -1837,8 +1831,7 @@ static void write_i2c_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x00 to 0x23 */ buffer[0 ] =0x00 ;
@@ -1849,8 +1842,7 @@ static void write_i2c_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0xff to 0x00 */ buffer[0 ] =0xff ;
@@ -1861,10 +1853,14 @@ static void write_i2c_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail; } + +return ; + +i2c_write_fail: +DC_LOG_DEBUG ("Set retimer failed" ); } static void write_i2c_default_retimer_setting(
@@ -1889,8 +1885,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x0A to 0x17 */ buffer[0 ] =0x0A ;
@@ -1901,8 +1896,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x0B to 0xDA or 0xD8 */ buffer[0 ] =0x0B ;
@@ -1913,8 +1907,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x0A to 0x17 */ buffer[0 ] =0x0A ;
@@ -1925,8 +1918,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x0C to 0x1D or 0x91 */ buffer[0 ] =0x0C ;
@@ -1937,8 +1929,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x0A to 0x17 */ buffer[0 ] =0x0A ;
@@ -1949,8 +1940,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;if (is_vga_mode) {
@@ -1965,8 +1955,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0x00 to 0x23 */ buffer[0 ] =0x00 ;
@@ -1977,8 +1966,7 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail;/* Write offset 0xff to 0x00 */ buffer[0 ] =0xff ;
@@ -1989,9 +1977,13 @@ static void write_i2c_default_retimer_setting( offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n", slave_address, buffer[0], buffer[1], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); + goto i2c_write_fail; } + +return ; + +i2c_write_fail: +DC_LOG_DEBUG ("Set default retimer failed" ); } static void write_i2c_redriver_setting(
@@ -2020,8 +2012,7 @@ static void write_i2c_redriver_setting( slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0);if (!i2c_success) -/* Write failure */ -ASSERT (i2c_success); +DC_LOG_DEBUG ("Set redriver failed" ); }static void enable_link_hdmi (struct pipe_ctx *pipe_ctx)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 155/388 clk: imx: Fix division by zero warning on pfdv2
In reply to Greg Kroah-HartmanFrom: Anson Huang <[email protected]>
[ Upstream commit 28b2f82e0383e27476be8a5e13d2aea07ebeb275 ]
Fix below division by zero warning:
[ 3.176443] Division by zero in kernel. [ 3.181809] CPU: 0 PID: 88 Comm: kworker/0:2 Not tainted 5.3.0-rc2-next-20190730-63758-ge08da51-dirty #124 [ 3.191817] Hardware name: Freescale i.MX7ULP (Device Tree) [ 3.197821] Workqueue: events dbs_work_handler [ 3.202849] [<c01127d8>] (unwind_backtrace) from [<c010cd80>] (show_stack+0x10/0x14) [ 3.211058] [<c010cd80>] (show_stack) from [<c0c77e68>] (dump_stack+0xd8/0x110) [ 3.218820] [<c0c77e68>] (dump_stack) from [<c0c753c0>] (Ldiv0_64+0x8/0x18) [ 3.226263] [<c0c753c0>] (Ldiv0_64) from [<c05984b4>] (clk_pfdv2_set_rate+0x54/0xac) [ 3.234487] [<c05984b4>] (clk_pfdv2_set_rate) from [<c059192c>] (clk_change_rate+0x1a4/0x698) [ 3.243468] [<c059192c>] (clk_change_rate) from [<c0591a08>] (clk_change_rate+0x280/0x698) [ 3.252180] [<c0591a08>] (clk_change_rate) from [<c0591fc0>] (clk_core_set_rate_nolock+0x1a0/0x278) [ 3.261679] [<c0591fc0>] (clk_core_set_rate_nolock) from [<c05920c8>] (clk_set_rate+0x30/0x64) [ 3.270743] [<c05920c8>] (clk_set_rate) from [<c089cb88>] (imx7ulp_set_target+0x184/0x2a4) [ 3.279501] [<c089cb88>] (imx7ulp_set_target) from [<c0896358>] (__cpufreq_driver_target+0x188/0x514) [ 3.289196] [<c0896358>] (__cpufreq_driver_target) from [<c0899b0c>] (od_dbs_update+0x130/0x15c) [ 3.298438] [<c0899b0c>] (od_dbs_update) from [<c089a5d0>] (dbs_work_handler+0x2c/0x5c) [ 3.306914] [<c089a5d0>] (dbs_work_handler) from [<c0156858>] (process_one_work+0x2ac/0x704) [ 3.315826] [<c0156858>] (process_one_work) from [<c0156cdc>] (worker_thread+0x2c/0x574) [ 3.324404] [<c0156cdc>] (worker_thread) from [<c015cfe8>] (kthread+0x134/0x148) [ 3.332278] [<c015cfe8>] (kthread) from [<c01010b4>] (ret_from_fork+0x14/0x20) [ 3.339858] Exception stack(0xe82d5fb0 to 0xe82d5ff8) [ 3.345314] 5fa0: 00000000 00000000 00000000 00000000 [ 3.353926] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 3.362519] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
--- drivers/clk/imx/clk-pfdv2.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/clk/imx/clk-pfdv2.c +6 -0
@@ -139,6 +139,12 @@ static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate,u32 val;u8 frac; +if (!rate) +return -EINVAL ; + +/* PFD can NOT change rate without gating */ +WARN_ON (clk_pfdv2_is_enabled (hw)); + tmp = tmp *18 + rate /2 ;do_div (tmp, rate); frac = tmp;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 156/388 cpu-topology: Fix the potential data corruption
In reply to Greg Kroah-HartmanFrom: Zeng Tao <[email protected]>
[ Upstream commit 4a33691c4cea9eb0a7c66e87248be4637e14b180 ]
Currently there are only 10 bytes to store the cpu-topology 'name' information. Only 10 bytes copied into cluster/thread/core names.
If the cluster ID exceeds 2-digit number, it will result in the data corruption, and ending up in a dead loop in the parsing routines. The same applies to the thread names with more that 3-digit number.
This issue was found using the boundary tests under virtualised environment like QEMU.
Let us increase the buffer to fix such potential issues.
--- drivers/base/arch_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/base/arch_topology.c +2 -2
@@ -270,7 +270,7 @@ static int __init get_cpu_for_node(struct device_node *node)static int __init parse_core (struct device_node *core,int package_id,int core_id) { -char name[10 ]; +char name[20 ];bool leaf = true;int i =0 ;int cpu;
@@ -317,7 +317,7 @@ static int __init parse_core(struct device_node *core, int package_id,static int __init parse_cluster (struct device_node *cluster,int depth) { -char name[10 ]; +char name[20 ];bool leaf = true;bool has_cores = false;struct device_node *c;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 157/388 s390/irq: replace setup_irq() by request_irq()
In reply to Greg Kroah-HartmanFrom: afzal mohammed <[email protected]>
[ Upstream commit 8719b6d29d2851fa84c4074bb2e5adc022911ab8 ]
request_irq() is preferred over setup_irq(). Invocations of setup_irq() occur after memory allocators are ready.
Per tglx[1], setup_irq() existed in olden days when allocators were not ready by the time early interrupts were initialized.
Hence replace setup_irq() by request_irq().
[1] https://lkml.kernel.org/r/alpine.DEB.2.20.1710191609480.1971@nanos
Message-Id: <[email protected]>
--- arch/s390/kernel/irq.c | 8 ++------ drivers/s390/cio/airq.c | 8 ++------ drivers/s390/cio/cio.c | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-)
arch/s390/kernel/irq.c +2 -6
@@ -294,11 +294,6 @@ static irqreturn_t do_ext_interrupt(int irq, void *dummy)return IRQ_HANDLED ; } -static struct irqaction external_interrupt = { - .name ="EXT" , - .handler = do_ext_interrupt, -}; -void __init init_ext_interrupts (void ) {int idx;
@@ -308,7 +303,8 @@ void __init init_ext_interrupts(void)irq_set_chip_and_handler (EXT_INTERRUPT , &dummy_irq_chip, handle_percpu_irq); -setup_irq (EXT_INTERRUPT , &external_interrupt); +if (request_irq (EXT_INTERRUPT , do_ext_interrupt,0 ,"EXT" ,NULL )) +panic ("Failed to register EXT interrupt\n" ); }static DEFINE_SPINLOCK (irq_subclass_lock);
drivers/s390/cio/airq.c +2 -6
@@ -105,16 +105,12 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy)return IRQ_HANDLED ; } -static struct irqaction airq_interrupt = { - .name ="AIO" , - .handler = do_airq_interrupt, -}; -void __init init_airq_interrupts (void ) {irq_set_chip_and_handler (THIN_INTERRUPT , &dummy_irq_chip, handle_percpu_irq); -setup_irq (THIN_INTERRUPT , &airq_interrupt); +if (request_irq (THIN_INTERRUPT , do_airq_interrupt,0 ,"AIO" ,NULL )) +panic ("Failed to register AIO interrupt\n" ); }static inline unsigned long iv_size (unsigned long bits)
drivers/s390/cio/cio.c +2 -6
@@ -563,16 +563,12 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)return IRQ_HANDLED ; } -static struct irqaction io_interrupt = { - .name ="I/O" , - .handler = do_cio_interrupt, -}; -void __init init_cio_interrupts (void ) {irq_set_chip_and_handler (IO_INTERRUPT , &dummy_irq_chip, handle_percpu_irq); -setup_irq (IO_INTERRUPT , &io_interrupt); +if (request_irq (IO_INTERRUPT , do_cio_interrupt,0 ,"I/O" ,NULL )) +panic ("Failed to register I/O interrupt\n" ); }#ifdef CONFIG_CCW_CONSOLE
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 158/388 perf cs-etm: Swap packets for instruction samples
In reply to Greg Kroah-HartmanFrom: Leo Yan <[email protected]>
[ Upstream commit d01751563caf0dec7be36f81de77cc0197b77e59 ]
If use option '--itrace=iNNN' with Arm CoreSight trace data, perf tool fails inject instruction samples; the root cause is the packets are only swapped for branch samples and last branches but not for instruction samples, so the new coming packets cannot be properly handled for only synthesizing instruction samples.
To fix this issue, this patch refactors the code with a new function cs_etm__packet_swap() which is used to swap packets and adds the condition for instruction samples.
--- tools/perf/util/cs-etm.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-)
tools/perf/util/cs-etm.c +19 -20
@@ -363,6 +363,23 @@ struct cs_etm_packet_queuereturn NULL ; } +static void cs_etm__packet_swap (struct cs_etm_auxtrace *etm, +struct cs_etm_traceid_queue *tidq) +{ +struct cs_etm_packet *tmp; + +if (etm->sample_branches || etm->synth_opts.last_branch || + etm->sample_instructions) { +/* +* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for +* the next incoming packet. +*/ + tmp = tidq->packet; + tidq->packet = tidq->prev_packet; + tidq->prev_packet = tmp; + } +} +static void cs_etm__packet_dump (const char *pkt_string) {const char *color =PERF_COLOR_BLUE ;
@@ -1340,7 +1357,6 @@ static int cs_etm__sample(struct cs_etm_queue *etmq, struct cs_etm_traceid_queue *tidq) {struct cs_etm_auxtrace *etm = etmq->etm; -struct cs_etm_packet *tmp;int ret;u8 trace_chan_id = tidq->trace_chan_id;u64 instrs_executed = tidq->packet->instr_count;
@@ -1404,15 +1420,7 @@ static int cs_etm__sample(struct cs_etm_queue *etmq, } } -if (etm->sample_branches || etm->synth_opts.last_branch) { -/* -* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for -* the next incoming packet. -*/ - tmp = tidq->packet; - tidq->packet = tidq->prev_packet; - tidq->prev_packet = tmp; - } +cs_etm__packet_swap (etm, tidq);return 0 ; }
@@ -1441,7 +1449,6 @@ static int cs_etm__flush(struct cs_etm_queue *etmq, {int err =0 ;struct cs_etm_auxtrace *etm = etmq->etm; -struct cs_etm_packet *tmp;/* Handle start tracing packet */ if (tidq->prev_packet->sample_type ==CS_ETM_EMPTY )
@@ -1476,15 +1483,7 @@ static int cs_etm__flush(struct cs_etm_queue *etmq, } swap_packet: -if (etm->sample_branches || etm->synth_opts.last_branch) { -/* -* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for -* the next incoming packet. -*/ - tmp = tidq->packet; - tidq->packet = tidq->prev_packet; - tidq->prev_packet = tmp; - } +cs_etm__packet_swap (etm, tidq);return err; }
Signature · 9 lines
2.25.1 _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Greg Kroah-Hartman
maintainerPATCH 159/388 perf cs-etm: Correct synthesizing instruction samples
In reply to Greg Kroah-HartmanFrom: Leo Yan <[email protected]>
[ Upstream commit c9f5baa136777b2c982f6f7a90c9da69a88be148 ]
When 'etm->instructions_sample_period' is less than 'tidq->period_instructions', the function cs_etm__sample() cannot handle this case properly with its logic.
Let's see below flow as an example:
- If we set itrace option '--itrace=i4', then function cs_etm__sample() has variables with initialized values:
tidq->period_instructions = 0
etm->instructions_sample_period = 4
- When the first packet is coming:
packet->instr_count = 10; the number of instructions executed in this packet is 10, thus update period_instructions as below:
tidq->period_instructions = 0 + 10 = 10
instrs_over = 10 - 4 = 6
offset = 10 - 6 - 1 = 3
tidq->period_instructions = instrs_over = 6
- When the second packet is coming:
packet->instr_count = 10; in the second pass, assume 10 instructions in the trace sample again:
tidq->period_instructions = 6 + 10 = 16 instrs_over = 16 - 4 = 12
offset = 10 - 12 - 1 = -3 -> the negative value tidq->period_instructions = instrs_over = 12
So after handle these two packets, there have below issues:
The first issue is that cs_etm__instr_addr() returns the address within the current trace sample of the instruction related to offset, so the offset is supposed to be always unsigned value. But in fact, function cs_etm__sample() might calculate a negative offset value (in handling the second packet, the offset is -3) and pass to cs_etm__instr_addr() with u64 type with a big positive integer.
The second issue is it only synthesizes 2 samples for sample period = 4. In theory, every packet has 10 instructions so the two packets have total 20 instructions, 20 instructions should generate 5 samples (4 x 5 = 20). This is because cs_etm__sample() only calls once cs_etm__synth_instruction_sample() to generate instruction sample per range packet.
This patch fixes the logic in function cs_etm__sample(); the basic idea for handling coming packet is:
- To synthesize the first instruction sample, it combines the left instructions from the previous packet and the head of the new packet; then generate continuous samples with sample period;
- At the tail of the new packet, if it has the rest instructions, these instructions will be left for the sequential sample.
--- tools/perf/util/cs-etm.c | 87 ++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 17 deletions(-)
tools/perf/util/cs-etm.c +70 -17
@@ -1359,9 +1359,12 @@ static int cs_etm__sample(struct cs_etm_queue *etmq,struct cs_etm_auxtrace *etm = etmq->etm;int ret;u8 trace_chan_id = tidq->trace_chan_id; -u64 instrs_executed = tidq->packet->instr_count; +u64 instrs_prev; - tidq->period_instructions += instrs_executed; +/* Get instructions remainder from previous packet */ + instrs_prev = tidq->period_instructions; + + tidq->period_instructions += tidq->packet->instr_count;/* * Record a branch when the last instruction in
@@ -1379,26 +1382,76 @@ static int cs_etm__sample(struct cs_etm_queue *etmq,* TODO: allow period to be defined in cycles and clock time */ -/* Get number of instructions executed after the sample point */ -u64 instrs_over = tidq->period_instructions - - etm->instructions_sample_period; +/* +* Below diagram demonstrates the instruction samples +* generation flows: +* +* Instrs Instrs Instrs Instrs +* Sample(n) Sample(n+1) Sample(n+2) Sample(n+3) +* | | | | +* V V V V +* -------------------------------------------------- +* ^ ^ +* | | +* Period Period +* instructions(Pi) instructions(Pi') +* +* | | +* \---------------- -----------------/ +* V +* tidq->packet->instr_count +* +* Instrs Sample(n...) are the synthesised samples occurring +* every etm->instructions_sample_period instructions - as +* defined on the perf command line. Sample(n) is being the +* last sample before the current etm packet, n+1 to n+3 +* samples are generated from the current etm packet. +* +* tidq->packet->instr_count represents the number of +* instructions in the current etm packet. +* +* Period instructions (Pi) contains the the number of +* instructions executed after the sample point(n) from the +* previous etm packet. This will always be less than +* etm->instructions_sample_period. +* +* When generate new samples, it combines with two parts +* instructions, one is the tail of the old packet and another +* is the head of the new coming packet, to generate +* sample(n+1); sample(n+2) and sample(n+3) consume the +* instructions with sample period. After sample(n+3), the rest +* instructions will be used by later packet and it is assigned +* to tidq->period_instructions for next round calculation. +*/ /* -* Calculate the address of the sampled instruction (-1 as -* sample is reported as though instruction has just been -* executed, but PC has not advanced to next instruction) +* Get the initial offset into the current packet instructions; +* entry conditions ensure that instrs_prev is less than +* etm->instructions_sample_period. */ -u64 offset = (instrs_executed - instrs_over -1 ); -u64 addr =cs_etm__instr_addr (etmq, trace_chan_id, - tidq->packet, offset); +u64 offset = etm->instructions_sample_period - instrs_prev; +u64 addr; - ret =cs_etm__synth_instruction_sample ( - etmq, tidq, addr, etm->instructions_sample_period); -if (ret) -return ret; +while (tidq->period_instructions >= + etm->instructions_sample_period) { +/* +* Calculate the address of the sampled instruction (-1 +* as sample is reported as though instruction has just +* been executed, but PC has not advanced to next +* instruction) +*/ + addr =cs_etm__instr_addr (etmq, trace_chan_id, + tidq->packet, offset -1 ); + ret =cs_etm__synth_instruction_sample ( + etmq, tidq, addr, + etm->instructions_sample_period); +if (ret) +return ret; -/* Carry remaining instructions into next sample period */ - tidq->period_instructions = instrs_over; + offset += etm->instructions_sample_period; + tidq->period_instructions -= + etm->instructions_sample_period; + } }if (etm->sample_branches) {
Signature · 9 lines
2.25.1 _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Greg Kroah-Hartman
maintainerPATCH 160/388 ath10k: use kzalloc to read for ath10k_sdio_hif_diag_read
In reply to Greg Kroah-HartmanFrom: Wen Gong <[email protected]>
[ Upstream commit 402f2992b4d62760cce7c689ff216ea3bf4d6e8a ]
When use command to read values, it crashed.
command:
dd if=/sys/kernel/debug/ieee80211/phy0/ath10k/mem_value count=1 bs=4 skip=$((0x100233))
It will call to ath10k_sdio_hif_diag_read with address = 0x4008cc and buf_len = 4.
Then system crash:
[ 1786.013258] Unable to handle kernel paging request at virtual address ffffffc00bd45000 [ 1786.013273] Mem abort info: [ 1786.013281] ESR = 0x96000045 [ 1786.013291] Exception class = DABT (current EL), IL = 32 bits [ 1786.013299] SET = 0, FnV = 0 [ 1786.013307] EA = 0, S1PTW = 0 [ 1786.013314] Data abort info: [ 1786.013322] ISV = 0, ISS = 0x00000045 [ 1786.013330] CM = 0, WnR = 1 [ 1786.013342] swapper pgtable: 4k pages, 39-bit VAs, pgdp = 000000008542a60e [ 1786.013350] [ffffffc00bd45000] pgd=0000000000000000, pud=0000000000000000 [ 1786.013368] Internal error: Oops: 96000045 [#1] PREEMPT SMP [ 1786.013609] Process swapper/0 (pid: 0, stack limit = 0x0000000084b153c6) [ 1786.013623] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.19.86 #137 [ 1786.013631] Hardware name: MediaTek krane sku176 board (DT) [ 1786.013643] pstate: 80000085 (Nzcv daIf -PAN -UAO) [ 1786.013662] pc : __memcpy+0x94/0x180 [ 1786.013678] lr : swiotlb_tbl_unmap_single+0x84/0x150 [ 1786.013686] sp : ffffff8008003c60 [ 1786.013694] x29: ffffff8008003c90 x28: ffffffae96411f80 [ 1786.013708] x27: ffffffae960d2018 x26: ffffff8019a4b9a8 [ 1786.013721] x25: 0000000000000000 x24: 0000000000000001 [ 1786.013734] x23: ffffffae96567000 x22: 00000000000051d4 [ 1786.013747] x21: 0000000000000000 x20: 00000000fe6e9000 [ 1786.013760] x19: 0000000000000004 x18: 0000000000000020 [ 1786.013773] x17: 0000000000000001 x16: 0000000000000000 [ 1786.013787] x15: 00000000ffffffff x14: 00000000000044c0 [ 1786.013800] x13: 0000000000365ba4 x12: 0000000000000000 [ 1786.013813] x11: 0000000000000001 x10: 00000037be6e9000 [ 1786.013826] x9 : ffffffc940000000 x8 : 000000000bd45000 [ 1786.013839] x7 : 0000000000000000 x6 : ffffffc00bd45000 [ 1786.013852] x5 : 0000000000000000 x4 : 0000000000000000 [ 1786.013865] x3 : 0000000000000c00 x2 : 0000000000000004 [ 1786.013878] x1 : fffffff7be6e9004 x0 : ffffffc00bd45000 [ 1786.013891] Call trace: [ 1786.013903] __memcpy+0x94/0x180 [ 1786.013914] unmap_single+0x6c/0x84 [ 1786.013925] swiotlb_unmap_sg_attrs+0x54/0x80 [ 1786.013938] __swiotlb_unmap_sg_attrs+0x8c/0xa4 [ 1786.013952] msdc_unprepare_data+0x6c/0x84 [ 1786.013963] msdc_request_done+0x58/0x84 [ 1786.013974] msdc_data_xfer_done+0x1a0/0x1c8 [ 1786.013985] msdc_irq+0x12c/0x17c [ 1786.013996] __handle_irq_event_percpu+0xe4/0x250 [ 1786.014006] handle_irq_event_percpu+0x28/0x68 [ 1786.014015] handle_irq_event+0x48/0x78 [ 1786.014026] handle_fasteoi_irq+0xd0/0x1a0 [ 1786.014039] __handle_domain_irq+0x84/0xc4 [ 1786.014050] gic_handle_irq+0x124/0x1a4 [ 1786.014059] el1_irq+0xb0/0x128 [ 1786.014072] cpuidle_enter_state+0x298/0x328 [ 1786.014082] cpuidle_enter+0x30/0x40 [ 1786.014094] do_idle+0x190/0x268 [ 1786.014104] cpu_startup_entry+0x24/0x28 [ 1786.014116] rest_init+0xd4/0xe0 [ 1786.014126] start_kernel+0x30c/0x38c [ 1786.014139] Code: f8408423 f80084c3 36100062 b8404423 (b80044c3) [ 1786.014150] ---[ end trace 3b02ddb698ea69ee ]--- [ 1786.015415] Kernel panic - not syncing: Fatal exception in interrupt [ 1786.015433] SMP: stopping secondary CPUs [ 1786.015447] Kernel Offset: 0x2e8d200000 from 0xffffff8008000000 [ 1786.015458] CPU features: 0x0,2188200c [ 1786.015466] Memory Limit: none
For sdio chip, it need the memory which is kmalloc, if it is vmalloc from ath10k_mem_value_read, then it have a memory error. kzalloc of ath10k_sdio_hif_diag_read32 is the correct type, so add kzalloc in ath10k_sdio_hif_diag_read to replace the buffer which is vmalloc from ath10k_mem_value_read.
This patch only effect sdio chip.
Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00029.
--- drivers/net/wireless/ath/ath10k/sdio.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
drivers/net/wireless/ath/ath10k/sdio.c +14 -4
@@ -1582,23 +1582,33 @@ static int ath10k_sdio_hif_diag_read(struct ath10k *ar, u32 address, void *buf, size_t buf_len) {int ret; +void *mem; + + mem =kzalloc (buf_len,GFP_KERNEL ); +if (!mem) +return -ENOMEM ;/* set window register to start read cycle */ ret =ath10k_sdio_write32 (ar,MBOX_WINDOW_READ_ADDR_ADDRESS , address);if (ret) {ath10k_warn (ar,"failed to set mbox window read address: %d" , ret); -return ret; + goto out; }/* read the data */ - ret =ath10k_sdio_read (ar,MBOX_WINDOW_DATA_ADDRESS , buf, buf_len); + ret =ath10k_sdio_read (ar,MBOX_WINDOW_DATA_ADDRESS , mem, buf_len);if (ret) {ath10k_warn (ar,"failed to read from mbox window data address: %d\n" , ret); -return ret; + goto out; } -return 0 ; +memcpy (buf, mem, buf_len); + +out: +kfree (mem); + +return ret; } static int ath10k_sdio_hif_diag_read32(struct ath10k *ar, u32 address,
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 161/388 scsi: aacraid: Disabling TM path and only processing IOP reset
In reply to Greg Kroah-HartmanFrom: Sagar Biradar <[email protected]>
[ Upstream commit bef18d308a2215eff8c3411a23d7f34604ce56c3 ]
Fixes the occasional adapter panic when sg_reset is issued with -d, -t, -b and -H flags. Removal of command type HBA_IU_TYPE_SCSI_TM_REQ in aac_hba_send since iu_type, request_id and fib_flags are not populated. Device and target reset handlers are made to send TMF commands only when reset_state is 0.
--- drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/aacraid/linit.c | 34 +++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-)
drivers/scsi/aacraid/commsup.c +1 -1
@@ -728,7 +728,7 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, hbacmd->request_id =cpu_to_le32 ((((u32)(fibptr - dev->fibs)) <<2 ) +1 ); fibptr->flags |=FIB_CONTEXT_FLAG_SCSI_CMD ; - }else if (command !=HBA_IU_TYPE_SCSI_TM_REQ ) + }else return -EINVAL ;
drivers/scsi/aacraid/linit.c +25 -9
@@ -723,7 +723,11 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) status =aac_hba_send (HBA_IU_TYPE_SCSI_TM_REQ , fib, (fib_callback ) aac_hba_callback, (void *) cmd); - +if (status != -EINPROGRESS ) { +aac_fib_complete (fib); +aac_fib_free (fib); +return ret; + }/* Wait up to 15 secs for completion */ for (count =0 ; count <15 ; ++count) {if (cmd->SCp.sent_command) {
@@ -902,11 +906,11 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) info = &aac->hba_map[bus][cid]; -if (info->devtype !=AAC_DEVTYPE_NATIVE_RAW && - info->reset_state >0 ) +if (!(info->devtype ==AAC_DEVTYPE_NATIVE_RAW && + !(info->reset_state >0 )))return FAILED ; -pr_err ("%s: Host adapter reset request. SCSI hang ?\n" , +pr_err ("%s: Host device reset request. SCSI hang ?\n" ,AAC_DRIVERNAME ); fib =aac_fib_alloc (aac);
@@ -921,7 +925,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) status =aac_hba_send (command, fib, (fib_callback ) aac_tmf_callback, (void *) info); - +if (status != -EINPROGRESS ) { + info->reset_state =0 ; +aac_fib_complete (fib); +aac_fib_free (fib); +return ret; + }/* Wait up to 15 seconds for completion */ for (count =0 ; count <15 ; ++count) {if (info->reset_state ==0 ) {
@@ -960,11 +969,11 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) info = &aac->hba_map[bus][cid]; -if (info->devtype !=AAC_DEVTYPE_NATIVE_RAW && - info->reset_state >0 ) +if (!(info->devtype ==AAC_DEVTYPE_NATIVE_RAW && + !(info->reset_state >0 )))return FAILED ; -pr_err ("%s: Host adapter reset request. SCSI hang ?\n" , +pr_err ("%s: Host target reset request. SCSI hang ?\n" ,AAC_DRIVERNAME ); fib =aac_fib_alloc (aac);
@@ -981,6 +990,13 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) (fib_callback ) aac_tmf_callback, (void *) info); +if (status != -EINPROGRESS ) { + info->reset_state =0 ; +aac_fib_complete (fib); +aac_fib_free (fib); +return ret; + } +/* Wait up to 15 seconds for completion */ for (count =0 ; count <15 ; ++count) {if (info->reset_state <=0 ) {
@@ -1033,7 +1049,7 @@ static int aac_eh_bus_reset(struct scsi_cmnd* cmd) } } -pr_err ("%s: Host adapter reset request. SCSI hang ?\n" ,AAC_DRIVERNAME ); +pr_err ("%s: Host bus reset request. SCSI hang ?\n" ,AAC_DRIVERNAME );/* * Check the health of the controller
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 162/388 Bluetooth: L2CAP: handle l2cap config request during open state
In reply to Greg Kroah-HartmanFrom: Howard Chung <[email protected]>
[ Upstream commit 96298f640104e4cd9a913a6e50b0b981829b94ff ]
According to Core Spec Version 5.2 | Vol 3, Part A 6.1.5, the incoming L2CAP_ConfigReq should be handled during OPEN state.
The section below shows the btmon trace when running L2CAP/COS/CFD/BV-12-C before and after this change.
=== Before ===
...
Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 12 #22
L2CAP: Connection Request (0x02) ident 2 len 4
PSM: 1 (0x0001)
Source CID: 65
< ACL Data TX: Handle 256 flags 0x00 dlen 16 #23
L2CAP: Connection Response (0x03) ident 2 len 8
Destination CID: 64
Source CID: 65
Result: Connection successful (0x0000)
Status: No further information available (0x0000)
< ACL Data TX: Handle 256 flags 0x00 dlen 12 #24
L2CAP: Configure Request (0x04) ident 2 len 4
Destination CID: 65
Flags: 0x0000Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #25
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #26
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 16 #27
L2CAP: Configure Request (0x04) ident 3 len 8
Destination CID: 64
Flags: 0x0000
Option: Unknown (0x10) [hint]
01 00 ..
< ACL Data TX: Handle 256 flags 0x00 dlen 18 #28
L2CAP: Configure Response (0x05) ident 3 len 10
Source CID: 65
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 672Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #29
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 14 #30
L2CAP: Configure Response (0x05) ident 2 len 6
Source CID: 64
Flags: 0x0000
Result: Success (0x0000)Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 20 #31
L2CAP: Configure Request (0x04) ident 3 len 12
Destination CID: 64
Flags: 0x0000
Option: Unknown (0x10) [hint]
01 00 91 02 11 11 ......< ACL Data TX: Handle 256 flags 0x00 dlen 14 #32
L2CAP: Command Reject (0x01) ident 3 len 6
Reason: Invalid CID in request (0x0002) Destination CID: 64
Source CID: 65
Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #33
Num handles: 1
Handle: 256
Count: 1
...
=== After ===
...
Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 12 #22
L2CAP: Connection Request (0x02) ident 2 len 4
PSM: 1 (0x0001)
Source CID: 65
< ACL Data TX: Handle 256 flags 0x00 dlen 16 #23
L2CAP: Connection Response (0x03) ident 2 len 8
Destination CID: 64
Source CID: 65
Result: Connection successful (0x0000)
Status: No further information available (0x0000)
< ACL Data TX: Handle 256 flags 0x00 dlen 12 #24
L2CAP: Configure Request (0x04) ident 2 len 4
Destination CID: 65
Flags: 0x0000Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #25
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #26
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 16 #27
L2CAP: Configure Request (0x04) ident 3 len 8
Destination CID: 64
Flags: 0x0000
Option: Unknown (0x10) [hint]
01 00 ..
< ACL Data TX: Handle 256 flags 0x00 dlen 18 #28
L2CAP: Configure Response (0x05) ident 3 len 10
Source CID: 65
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 672Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #29
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 14 #30
L2CAP: Configure Response (0x05) ident 2 len 6
Source CID: 64
Flags: 0x0000
Result: Success (0x0000)Quoted 1 line
ACL Data RX: Handle 256 flags
0x02dlen 20 #31
L2CAP: Configure Request (0x04) ident 3 len 12
Destination CID: 64
Flags: 0x0000
Option: Unknown (0x10) [hint]
01 00 91 02 11 11 .....
< ACL Data TX: Handle 256 flags 0x00 dlen 18 #32
L2CAP: Configure Response (0x05) ident 3 len 10
Source CID: 65
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 672
< ACL Data TX: Handle 256 flags 0x00 dlen 12 #33
L2CAP: Configure Request (0x04) ident 3 len 4
Destination CID: 65
Flags: 0x0000Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #34
Num handles: 1
Handle: 256
Count: 1
Quoted 1 line
HCI Event: Number of Completed Packets (
0x13) plen 5 #35
Num handles: 1
Handle: 256
Count: 1
...
--- net/bluetooth/l2cap_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +2 -1
@@ -4134,7 +4134,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,return 0 ; } -if (chan->state !=BT_CONFIG && chan->state !=BT_CONNECT2 ) { +if (chan->state !=BT_CONFIG && chan->state !=BT_CONNECT2 && + chan->state !=BT_CONNECTED ) {cmd_reject_invalid_cid (conn, cmd->ident, chan->scid, chan->dcid); goto unlock;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 163/388 media: tda10071: fix unsigned sign extension overflow
In reply to Greg Kroah-HartmanFrom: Colin Ian King <[email protected]>
[ Upstream commit a7463e2dc698075132de9905b89f495df888bb79 ]
The shifting of buf[3] by 24 bits to the left will be promoted to a 32 bit signed int and then sign-extended to an unsigned long. In the unlikely event that the the top bit of buf[3] is set then all then all the upper bits end up as also being set because of the sign-extension and this affect the ev->post_bit_error sum. Fix this by using the temporary u32 variable bit_error to avoid the sign-extension promotion. This also removes the need to do the computation twice.
Addresses-Coverity: ("Unintended sign extension")
--- drivers/media/dvb-frontends/tda10071.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/media/dvb-frontends/tda10071.c +5 -4
@@ -470,10 +470,11 @@ static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status) goto error;if (dev->delivery_system ==SYS_DVBS ) { - dev->dvbv3_ber = buf[0 ] <<24 | buf[1 ] <<16 | - buf[2 ] <<8 | buf[3 ] <<0 ; - dev->post_bit_error += buf[0 ] <<24 | buf[1 ] <<16 | - buf[2 ] <<8 | buf[3 ] <<0 ; +u32 bit_error = buf[0 ] <<24 | buf[1 ] <<16 | + buf[2 ] <<8 | buf[3 ] <<0 ; + + dev->dvbv3_ber = bit_error; + dev->post_bit_error += bit_error; c->post_bit_error.stat[0 ].scale =FE_SCALE_COUNTER ; c->post_bit_error.stat[0 ].uvalue = dev->post_bit_error; dev->block_error += buf[4 ] <<8 | buf[5 ] <<0 ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 164/388 tty: sifive: Finish transmission before changing the clock
In reply to Greg Kroah-HartmanFrom: Palmer Dabbelt <[email protected]>
[ Upstream commit 4cbd7814bbd595061fcb6d6355d63f04179161cd ]
SiFive's UART has a software controller clock divider that produces the final baud rate clock. Whenever the clock that drives the UART is changed this divider must be updated accordingly, and given that these two events are controlled by software they cannot be done atomically. During the period between updating the UART's driving clock and internal divider the UART will transmit a different baud rate than what the user has configured, which will probably result in a corrupted transmission stream.
The SiFive UART has a FIFO, but due to an issue with the programming interface there is no way to directly determine when the UART has finished transmitting. We're essentially restricted to dead reckoning in order to figure that out: we can use the FIFO's TX busy register to figure out when the last frame has begun transmission and just delay for a long enough that the last frame is guaranteed to get out.
As far as the actual implementation goes: I've modified the existing existing clock notifier function to drain both the FIFO and the shift register in on PRE_RATE_CHANGE. As far as I know there is no hardware flow control in this UART, so there's no good way to ask the other end to stop transmission while we can't receive (inserting software flow control messages seems like a bad idea here).
--- drivers/tty/serial/sifive.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
drivers/tty/serial/sifive.c +24 -4
@@ -618,10 +618,10 @@ static void sifive_serial_shutdown(struct uart_port *port)* * On the V0 SoC, the UART IP block is derived from the CPU clock source * after a synchronous divide-by-two divider, so any CPU clock rate change -* requires the UART baud rate to be updated. This presumably could corrupt any -* serial word currently being transmitted or received. It would probably -* be better to stop receives and transmits, then complete the baud rate -* change, then re-enable them. +* requires the UART baud rate to be updated. This presumably corrupts any +* serial word currently being transmitted or received. In order to avoid +* corrupting the output data stream, we drain the transmit queue before +* allowing the clock's rate to be changed. */ static int sifive_serial_clk_notifier (struct notifier_block *nb,unsigned long event,void *data)
@@ -629,6 +629,26 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb,struct clk_notifier_data *cnd = data;struct sifive_serial_port *ssp =notifier_to_sifive_serial_port (nb); +if (event ==PRE_RATE_CHANGE ) { +/* +* The TX watermark is always set to 1 by this driver, which +* means that the TX busy bit will lower when there are 0 bytes +* left in the TX queue -- in other words, when the TX FIFO is +* empty. +*/ +__ssp_wait_for_xmitr (ssp); +/* +* On the cycle the TX FIFO goes empty there is still a full +* UART frame left to be transmitted in the shift register. +* The UART provides no way for software to directly determine +* when that last frame has been transmitted, so we just sleep +* here instead. As we're not tracking the number of stop bits +* they're just worst cased here. The rest of the serial +* framing parameters aren't configurable by software. +*/ +udelay (DIV_ROUND_UP (12 *1000 *1000 , ssp->baud_rate)); + } +if (event ==POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) { ssp->clkin_rate = cnd->new_rate;__ssp_update_div (ssp);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 165/388 xfs: dont ever return a stale pointer from __xfs_dir3_free_read
In reply to Greg Kroah-HartmanFrom: Darrick J. Wong <[email protected]>
[ Upstream commit 1cb5deb5bc095c070c09a4540c45f9c9ba24be43 ]
If we decide that a directory free block is corrupt, we must take care not to leak a buffer pointer to the caller. After xfs_trans_brelse returns, the buffer can be freed or reused, which means that we have to set *bpp back to NULL.
Callers are supposed to notice the nonzero return value and not use the buffer pointer, but we should code more defensively, even if all current callers handle this situation correctly.
--- fs/xfs/libxfs/xfs_dir2_node.c | 1 + 1 file changed, 1 insertion(+)
fs/xfs/libxfs/xfs_dir2_node.c +1 -0
@@ -210,6 +210,7 @@ __xfs_dir3_free_read(if (fa) {xfs_verifier_error (*bpp, -EFSCORRUPTED , fa);xfs_trans_brelse (tp, *bpp); + *bpp =NULL ;return -EFSCORRUPTED ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 166/388 xfs: mark dir corrupt when lookup-by-hash fails
In reply to Greg Kroah-HartmanFrom: Darrick J. Wong <[email protected]>
[ Upstream commit 2e107cf869eecc770e3f630060bb4e5f547d0fd8 ]
In xchk_dir_actor, we attempt to validate the directory hash structures by performing a directory entry lookup by (hashed) name. If the lookup returns ENOENT, that means that the hash information is corrupt. The _process_error functions don't catch this, so we have to add that explicitly.
--- fs/xfs/scrub/dir.c | 3 +++ 1 file changed, 3 insertions(+)
fs/xfs/scrub/dir.c +3 -0
@@ -152,6 +152,9 @@ xchk_dir_actor( xname.type =XFS_DIR3_FT_UNKNOWN ; error =xfs_dir_lookup (sdc->sc->tp, ip, &xname, &lookup_ino,NULL ); +/* ENOENT means the hash lookup failed and the dir is corrupt */ +if (error == -ENOENT ) + error = -EFSCORRUPTED ;if (!xchk_fblock_process_error (sdc->sc,XFS_DATA_FORK , offset, &error)) goto out;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 167/388 ext4: mark block bitmap corrupted when found instead of BUGON
In reply to Greg Kroah-HartmanFrom: Dmitry Monakhov <[email protected]>
[ Upstream commit eb5760863fc28feab28b567ddcda7e667e638da0 ]
We already has similar code in ext4_mb_complex_scan_group(), but ext4_mb_simple_scan_group() still affected.
Other reports: https://www.spinics.net/lists/linux-ext4/msg60231.html
--- fs/ext4/mballoc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
fs/ext4/mballoc.c +9 -2
@@ -1901,8 +1901,15 @@ void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,BUG_ON (buddy ==NULL ); k =mb_find_next_zero_bit (buddy, max,0 ); -BUG_ON (k >= max); - +if (k >= max) { +ext4_grp_locked_error (ac->ac_sb, e4b->bd_group,0 ,0 , +"%d free clusters of order %d. But found 0" , + grp->bb_counters[i], i); +ext4_mark_group_bitmap_corrupted (ac->ac_sb, + e4b->bd_group, +EXT4_GROUP_INFO_BBITMAP_CORRUPT ); +break ; + } ac->ac_found++; ac->ac_b_ex.fe_len =1 << i;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 168/388 tpm: ibmvtpm: Wait for buffer to be set before proceeding
In reply to Greg Kroah-HartmanFrom: Stefan Berger <[email protected]>
[ Upstream commit d8d74ea3c00214aee1e1826ca18e77944812b9b4 ]
Synchronize with the results from the CRQs before continuing with the initialization. This avoids trying to send TPM commands while the rtce buffer has not been allocated, yet.
This patch fixes an existing race condition that may occurr if the hypervisor does not quickly respond to the VTPM_GET_RTCE_BUFFER_SIZE request sent during initialization and therefore the ibmvtpm->rtce_buf has not been allocated at the time the first TPM command is sent.
--- drivers/char/tpm/tpm_ibmvtpm.c | 9 +++++++++ drivers/char/tpm/tpm_ibmvtpm.h | 1 + 2 files changed, 10 insertions(+)
drivers/char/tpm/tpm_ibmvtpm.c +9 -0
@@ -581,6 +581,7 @@ static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)*/ while ((crq =ibmvtpm_crq_get_next (ibmvtpm)) !=NULL ) {ibmvtpm_crq_process (crq, ibmvtpm); +wake_up_interruptible (&ibmvtpm->crq_queue.wq); crq->valid =0 ;smp_wmb (); }
@@ -628,6 +629,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, } crq_q->num_entry =CRQ_RES_BUF_SIZE /sizeof (*crq_q->crq_addr); +init_waitqueue_head (&crq_q->wq); ibmvtpm->crq_dma_handle =dma_map_single (dev, crq_q->crq_addr,CRQ_RES_BUF_SIZE ,DMA_BIDIRECTIONAL );
@@ -680,6 +682,13 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,if (rc) goto init_irq_cleanup; +if (!wait_event_timeout (ibmvtpm->crq_queue.wq, + ibmvtpm->rtce_buf !=NULL , +HZ )) { +dev_err (dev,"CRQ response timed out\n" ); + goto init_irq_cleanup; + } +return tpm_chip_register (chip); init_irq_cleanup: do {
drivers/char/tpm/tpm_ibmvtpm.h +1 -0
@@ -26,6 +26,7 @@ struct ibmvtpm_crq_queue {struct ibmvtpm_crq *crq_addr;u32 index;u32 num_entry; +wait_queue_head_t wq; };struct ibmvtpm_dev {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 169/388 rtc: sa1100: fix possible race condition
In reply to Greg Kroah-HartmanFrom: Alexandre Belloni <[email protected]>
[ Upstream commit f2997775b111c6d660c32a18d5d44d37cb7361b1 ]
Both RTC IRQs are requested before the struct rtc_device is allocated, this may lead to a NULL pointer dereference in the IRQ handler.
To fix this issue, allocating the rtc_device struct before requesting the IRQs using devm_rtc_allocate_device, and use rtc_register_device to register the RTC device.
--- drivers/rtc/rtc-sa1100.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/rtc/rtc-sa1100.c +10 -8
@@ -182,7 +182,6 @@ static const struct rtc_class_ops sa1100_rtc_ops = {int sa1100_rtc_init (struct platform_device *pdev,struct sa1100_rtc *info) { -struct rtc_device *rtc;int ret;spin_lock_init (&info->lock);
@@ -211,15 +210,14 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)writel_relaxed (0 , info->rcnr); } - rtc =devm_rtc_device_register (&pdev->dev, pdev->name, &sa1100_rtc_ops, -THIS_MODULE ); -if (IS_ERR (rtc)) { + info->rtc->ops = &sa1100_rtc_ops; + info->rtc->max_user_freq =RTC_FREQ ; + + ret =rtc_register_device (info->rtc); +if (ret) {clk_disable_unprepare (info->clk); -return PTR_ERR (rtc); +return ret; } - info->rtc = rtc; - - rtc->max_user_freq =RTC_FREQ ;/* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_interrupt().
@@ -268,6 +266,10 @@ static int sa1100_rtc_probe(struct platform_device *pdev) info->irq_1hz = irq_1hz; info->irq_alarm = irq_alarm; + info->rtc =devm_rtc_allocate_device (&pdev->dev); +if (IS_ERR (info->rtc)) +return PTR_ERR (info->rtc); + ret =devm_request_irq (&pdev->dev, irq_1hz, sa1100_rtc_interrupt,0 ,"rtc 1Hz" , &pdev->dev);if (ret) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 170/388 rtc: ds1374: fix possible race condition
In reply to Greg Kroah-HartmanFrom: Alexandre Belloni <[email protected]>
[ Upstream commit c11af8131a4e7ba1960faed731ee7e84c2c13c94 ]
The RTC IRQ is requested before the struct rtc_device is allocated, this may lead to a NULL pointer dereference in the IRQ handler.
To fix this issue, allocating the rtc_device struct before requesting the RTC IRQ using devm_rtc_allocate_device, and use rtc_register_device to register the RTC device.
--- drivers/rtc/rtc-ds1374.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
drivers/rtc/rtc-ds1374.c +9 -6
@@ -620,6 +620,10 @@ static int ds1374_probe(struct i2c_client *client,if (!ds1374)return -ENOMEM ; + ds1374->rtc =devm_rtc_allocate_device (&client->dev); +if (IS_ERR (ds1374->rtc)) +return PTR_ERR (ds1374->rtc); + ds1374->client = client;i2c_set_clientdata (client, ds1374);
@@ -641,12 +645,11 @@ static int ds1374_probe(struct i2c_client *client,device_set_wakeup_capable (&client->dev,1 ); } - ds1374->rtc =devm_rtc_device_register (&client->dev, client->name, - &ds1374_rtc_ops,THIS_MODULE ); -if (IS_ERR (ds1374->rtc)) { -dev_err (&client->dev,"unable to register the class device\n" ); -return PTR_ERR (ds1374->rtc); - } + ds1374->rtc->ops = &ds1374_rtc_ops; + + ret =rtc_register_device (ds1374->rtc); +if (ret) +return ret;#ifdef CONFIG_RTC_DRV_DS1374_WDT save_client = client;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 171/388 nfsd: Dont add locks to closed or closing open stateids
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
[ Upstream commit a451b12311aa8c96c6f6e01c783a86995dc3ec6b ]
In NFSv4, the lock stateids are tied to the lockowner, and the open stateid, so that the action of closing the file also results in either an automatic loss of the locks, or an error of the form NFS4ERR_LOCKS_HELD.
In practice this means we must not add new locks to the open stateid after the close process has been invoked. In fact doing so, can result in the following panic:
kernel BUG at lib/list_debug.c:51!
invalid opcode: 0000 [#1] SMP NOPTI
CPU: 2 PID: 1085 Comm: nfsd Not tainted 5.6.0-rc3+ #2 Hardware name: VMware, Inc. VMware7,1/440BX Desktop Reference Platform, BIOS VMW71.00V.14410784.B64.1908150010 08/15/2019 RIP: 0010:__list_del_entry_valid.cold+0x31/0x55 Code: 1a 3d 9b e8 74 10 c2 ff 0f 0b 48 c7 c7 f0 1a 3d 9b e8 66 10 c2 ff 0f 0b 48 89 f2 48 89 fe 48 c7 c7 b0 1a 3d 9b e8 52 10 c2 ff <0f> 0b 48 89 fe 4c 89 c2 48 c7 c7 78 1a 3d 9b e8 3e 10 c2 ff 0f 0b RSP: 0018:ffffb296c1d47d90 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff8ba032456ec8 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff8ba039e99cc8 RDI: ffff8ba039e99cc8 RBP: ffff8ba032456e60 R08: 0000000000000781 R09: 0000000000000003 R10: 0000000000000000 R11: 0000000000000001 R12: ffff8ba009a4abe0 R13: ffff8ba032456e8c R14: 0000000000000000 R15: ffff8ba00adb01d8 FS: 0000000000000000(0000) GS:ffff8ba039e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fb213f0b008 CR3: 00000001347de006 CR4: 00000000003606e0 Call Trace: release_lock_stateid+0x2b/0x80 [nfsd] nfsd4_free_stateid+0x1e9/0x210 [nfsd] nfsd4_proc_compound+0x414/0x700 [nfsd] ? nfs4svc_decode_compoundargs+0x407/0x4c0 [nfsd] nfsd_dispatch+0xc1/0x200 [nfsd] svc_process_common+0x476/0x6f0 [sunrpc] ? svc_sock_secure_port+0x12/0x30 [sunrpc] ? svc_recv+0x313/0x9c0 [sunrpc] ? nfsd_svc+0x2d0/0x2d0 [nfsd] svc_process+0xd4/0x110 [sunrpc] nfsd+0xe3/0x140 [nfsd] kthread+0xf9/0x130 ? nfsd_destroy+0x50/0x50 [nfsd] ? kthread_park+0x90/0x90 ret_from_fork+0x1f/0x40
The fix is to ensure that lock creation tests for whether or not the open stateid is unhashed, and to fail if that is the case.
--- fs/nfsd/nfs4state.c | 73 ++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 30 deletions(-)
fs/nfsd/nfs4state.c +43 -30
@@ -495,6 +495,8 @@ find_any_file(struct nfs4_file *f) {struct nfsd_file *ret; +if (!f) +return NULL ;spin_lock (&f->fi_lock); ret =__nfs4_get_fd (f,O_RDWR );if (!ret) {
@@ -1273,6 +1275,12 @@ static void nfs4_put_stateowner(struct nfs4_stateowner *sop)nfs4_free_stateowner (sop); } +static bool +nfs4_ol_stateid_unhashed (const struct nfs4_ol_stateid *stp) +{ +return list_empty (&stp->st_perfile); +} +static bool unhash_ol_stateid (struct nfs4_ol_stateid *stp) {struct nfs4_file *fp = stp->st_stid.sc_file;
@@ -1343,9 +1351,11 @@ static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) {lockdep_assert_held (&stp->st_stid.sc_client->cl_lock); +if (!unhash_ol_stateid (stp)) +return false;list_del_init (&stp->st_locks);nfs4_unhash_stid (&stp->st_stid); -return unhash_ol_stateid (stp); +return true; }static void release_lock_stateid (struct nfs4_ol_stateid *stp)
@@ -1410,13 +1420,12 @@ static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp,static bool unhash_open_stateid (struct nfs4_ol_stateid *stp,struct list_head *reaplist) { -bool unhashed; -lockdep_assert_held (&stp->st_stid.sc_client->cl_lock); - unhashed =unhash_ol_stateid (stp); +if (!unhash_ol_stateid (stp)) +return false;release_open_stateid_locks (stp, reaplist); -return unhashed; +return true; }static void release_open_stateid (struct nfs4_ol_stateid *stp)
@@ -6267,21 +6276,21 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, }static struct nfs4_ol_stateid * -find_lock_stateid (struct nfs4_lockowner *lo,struct nfs4_file *fp) +find_lock_stateid (const struct nfs4_lockowner *lo, +const struct nfs4_ol_stateid *ost) {struct nfs4_ol_stateid *lst; -struct nfs4_client *clp = lo->lo_owner.so_client; -lockdep_assert_held (&clp->cl_lock); +lockdep_assert_held (&ost->st_stid.sc_client->cl_lock); -list_for_each_entry (lst, &lo->lo_owner.so_stateids, st_perstateowner) { -if (lst->st_stid.sc_type !=NFS4_LOCK_STID ) -continue ; -if (lst->st_stid.sc_file == fp) { -refcount_inc (&lst->st_stid.sc_count); -return lst; +/* If ost is not hashed, ost->st_locks will not be valid */ +if (!nfs4_ol_stateid_unhashed (ost)) +list_for_each_entry (lst, &ost->st_locks, st_locks) { +if (lst->st_stateowner == &lo->lo_owner) { +refcount_inc (&lst->st_stid.sc_count); +return lst; + } } - }return NULL ; }
@@ -6297,11 +6306,11 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,mutex_lock_nested (&stp->st_mutex,OPEN_STATEID_MUTEX ); retry:spin_lock (&clp->cl_lock); -spin_lock (&fp->fi_lock); - retstp =find_lock_stateid (lo, fp); +if (nfs4_ol_stateid_unhashed (open_stp)) + goto out_close; + retstp =find_lock_stateid (lo, open_stp);if (retstp) - goto out_unlock; - + goto out_found;refcount_inc (&stp->st_stid.sc_count); stp->st_stid.sc_type =NFS4_LOCK_STID ; stp->st_stateowner =nfs4_get_stateowner (&lo->lo_owner);
@@ -6310,22 +6319,26 @@ retry: stp->st_access_bmap =0 ; stp->st_deny_bmap = open_stp->st_deny_bmap; stp->st_openstp = open_stp; +spin_lock (&fp->fi_lock);list_add (&stp->st_locks, &open_stp->st_locks);list_add (&stp->st_perstateowner, &lo->lo_owner.so_stateids);list_add (&stp->st_perfile, &fp->fi_stateids); -out_unlock:spin_unlock (&fp->fi_lock);spin_unlock (&clp->cl_lock); -if (retstp) { -if (nfsd4_lock_ol_stateid (retstp) != nfs_ok) { -nfs4_put_stid (&retstp->st_stid); - goto retry; - } -/* To keep mutex tracking happy */ -mutex_unlock (&stp->st_mutex); - stp = retstp; - }return stp; +out_found: +spin_unlock (&clp->cl_lock); +if (nfsd4_lock_ol_stateid (retstp) != nfs_ok) { +nfs4_put_stid (&retstp->st_stid); + goto retry; + } +/* To keep mutex tracking happy */ +mutex_unlock (&stp->st_mutex); +return retstp; +out_close: +spin_unlock (&clp->cl_lock); +mutex_unlock (&stp->st_mutex); +return NULL ; } static struct nfs4_ol_stateid *
@@ -6340,7 +6353,7 @@ find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi, *new = false;spin_lock (&clp->cl_lock); - lst =find_lock_stateid (lo, fi); + lst =find_lock_stateid (lo, ost);spin_unlock (&clp->cl_lock);if (lst !=NULL ) {if (nfsd4_lock_ol_stateid (lst) == nfs_ok)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 172/388 RDMA/cm: Remove a race freeing timewait_info
In reply to Greg Kroah-HartmanFrom: Jason Gunthorpe <[email protected]>
[ Upstream commit bede86a39d9dc3387ac00dcb8e1ac221676b2f25 ]
When creating a cm_id during REQ the id immediately becomes visible to the other MAD handlers, and shortly after the state is moved to IB_CM_REQ_RCVD
This allows cm_rej_handler() to run concurrently and free the work:
CPU 0 CPU1
cm_req_handler()
ib_create_cm_id()
cm_match_req()
id_priv->state = IB_CM_REQ_RCVD
cm_rej_handler()
cm_acquire_id()
spin_lock(&id_priv->lock)
switch (id_priv->state)
case IB_CM_REQ_RCVD:
cm_reset_to_idle()
kfree(id_priv->timewait_info);
goto destroy
destroy:
kfree(id_priv->timewait_info);
id_priv->timewait_info = NULLCausing a double free or worse.
Do not free the timewait_info without also holding the id_priv->lock. Simplify this entire flow by making the free unconditional during cm_destroy_id() and removing the confusing special case error unwind during creation of the timewait_info.
This also fixes a leak of the timewait if cm_destroy_id() is called in IB_CM_ESTABLISHED with an XRC TGT QP. The state machine will be left in ESTABLISHED while it needed to transition through IB_CM_TIMEWAIT to release the timewait pointer.
Also fix a leak of the timewait_info if the caller mis-uses the API and does ib_send_cm_reqs().
--- drivers/infiniband/core/cm.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
drivers/infiniband/core/cm.c +15 -10
@@ -1092,14 +1092,22 @@ retest:break ; } -spin_lock_irq (&cm.lock); +spin_lock_irq (&cm_id_priv->lock); +spin_lock (&cm.lock); +/* Required for cleanup paths related cm_req_handler() */ +if (cm_id_priv->timewait_info) { +cm_cleanup_timewait (cm_id_priv->timewait_info); +kfree (cm_id_priv->timewait_info); + cm_id_priv->timewait_info =NULL ; + }if (!list_empty (&cm_id_priv->altr_list) && (!cm_id_priv->altr_send_port_not_ready))list_del (&cm_id_priv->altr_list);if (!list_empty (&cm_id_priv->prim_list) && (!cm_id_priv->prim_send_port_not_ready))list_del (&cm_id_priv->prim_list); -spin_unlock_irq (&cm.lock); +spin_unlock (&cm.lock); +spin_unlock_irq (&cm_id_priv->lock);cm_free_id (cm_id->local_id);cm_deref_id (cm_id_priv);
@@ -1416,7 +1424,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,/* Verify that we're not in timewait. */ cm_id_priv = container_of(cm_id, struct cm_id_private, id);spin_lock_irqsave (&cm_id_priv->lock, flags); -if (cm_id->state !=IB_CM_IDLE ) { +if (cm_id->state !=IB_CM_IDLE ||WARN_ON (cm_id_priv->timewait_info)) {spin_unlock_irqrestore (&cm_id_priv->lock, flags); ret = -EINVAL ; goto out;
@@ -1434,12 +1442,12 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, param->ppath_sgid_attr, &cm_id_priv->av, cm_id_priv);if (ret) - goto error1; + goto out;if (param->alternate_path) { ret =cm_init_av_by_path (param->alternate_path,NULL , &cm_id_priv->alt_av, cm_id_priv);if (ret) - goto error1; + goto out; } cm_id->service_id = param->service_id; cm_id->service_mask = ~cpu_to_be64 (0 );
@@ -1457,7 +1465,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, ret =cm_alloc_msg (cm_id_priv, &cm_id_priv->msg);if (ret) - goto error1; + goto out; req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;cm_format_req (req_msg, cm_id_priv, param);
@@ -1480,7 +1488,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,return 0 ; error2:cm_free_msg (cm_id_priv->msg); -error1:kfree (cm_id_priv->timewait_info); out:return ret; }EXPORT_SYMBOL (ib_send_cm_req);
@@ -1965,7 +1972,7 @@ static int cm_req_handler(struct cm_work *work)pr_debug ("%s: local_id %d, no listen_cm_id_priv\n" , __func__,be32_to_cpu (cm_id->local_id)); ret = -EINVAL ; - goto free_timeinfo; + goto destroy; } cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
@@ -2050,8 +2057,6 @@ static int cm_req_handler(struct cm_work *work) rejected:atomic_dec (&cm_id_priv->refcount);cm_deref_id (listen_cm_id_priv); -free_timeinfo: -kfree (cm_id_priv->timewait_info); destroy:ib_destroy_cm_id (cm_id);return ret;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 173/388 intel_th: Disallow multi mode on devices where its broken
In reply to Greg Kroah-HartmanFrom: Alexander Shishkin <[email protected]>
[ Upstream commit 397c7729665a3b07a7b4ce7215173df8e9112809 ]
Some versions of Intel TH have an issue that prevents the multi mode of MSU from working correctly, resulting in no trace data and potentially stuck MSU pipeline.
Disable multi mode on such devices.
--- drivers/hwtracing/intel_th/intel_th.h | 2 ++ drivers/hwtracing/intel_th/msu.c | 11 +++++++++-- drivers/hwtracing/intel_th/pci.c | 8 ++++++-- 3 files changed, 17 insertions(+), 4 deletions(-)
drivers/hwtracing/intel_th/intel_th.h +2 -0
@@ -47,11 +47,13 @@ struct intel_th_output {/** * struct intel_th_drvdata - describes hardware capabilities and quirks * @tscu_enable: device needs SW to enable time stamping unit +* @multi_is_broken: device has multiblock mode is broken * @has_mintctl: device has interrupt control (MINTCTL) register * @host_mode_only: device can only operate in 'host debugger' mode */ struct intel_th_drvdata {unsigned int tscu_enable :1 , + multi_is_broken :1 , has_mintctl :1 , host_mode_only :1 ; };
drivers/hwtracing/intel_th/msu.c +9 -2
@@ -157,7 +157,8 @@ struct msc {/* config */ unsigned int enabled : 1, wrap : 1, - do_irq : 1; + do_irq : 1, + multi_is_broken : 1;unsigned int mode;unsigned int burst_len;unsigned int index;
@@ -1665,7 +1666,7 @@ static int intel_th_msc_init(struct msc *msc) {atomic_set (&msc->user_count,-1 ); - msc->mode =MSC_MODE_MULTI ; + msc->mode = msc->multi_is_broken ?MSC_MODE_SINGLE :MSC_MODE_MULTI ;mutex_init (&msc->buf_mutex);INIT_LIST_HEAD (&msc->win_list);INIT_LIST_HEAD (&msc->iter_list);
@@ -1877,6 +1878,9 @@ mode_store(struct device *dev, struct device_attribute *attr, const char *buf,return -EINVAL ; found: +if (i ==MSC_MODE_MULTI && msc->multi_is_broken) +return -EOPNOTSUPP ; +mutex_lock (&msc->buf_mutex); ret =0 ;
@@ -2083,6 +2087,9 @@ static int intel_th_msc_probe(struct intel_th_device *thdev)if (!res) msc->do_irq =1 ; +if (INTEL_TH_CAP (to_intel_th (thdev), multi_is_broken)) + msc->multi_is_broken =1 ; + msc->index = thdev->id; msc->thdev = thdev;
drivers/hwtracing/intel_th/pci.c +6 -2
@@ -120,6 +120,10 @@ static void intel_th_pci_remove(struct pci_dev *pdev)pci_free_irq_vectors (pdev); } +static const struct intel_th_drvdata intel_th_1x_multi_is_broken = { + .multi_is_broken =1 , +}; +static const struct intel_th_drvdata intel_th_2x = { .tscu_enable =1 , .has_mintctl =1 ,
@@ -152,7 +156,7 @@ static const struct pci_device_id intel_th_pci_id_table[] = { {/* Kaby Lake PCH-H */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), - .driver_data = (kernel_ulong_t)0, + .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken, }, {/* Denverton */
@@ -207,7 +211,7 @@ static const struct pci_device_id intel_th_pci_id_table[] = { {/* Comet Lake PCH-V */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6), - .driver_data = (kernel_ulong_t)&intel_th_2x, + .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken, }, {/* Ice Lake NNPI */
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 174/388 KVM: PPC: Book3S HV: Treat TM-related invalid form instructions on P9 like the valid ones
In reply to Greg Kroah-HartmanFrom: Gustavo Romero <[email protected]>
[ Upstream commit 1dff3064c764b5a51c367b949b341d2e38972bec ]
On P9 DD2.2 due to a CPU defect some TM instructions need to be emulated by KVM. This is handled at first by the hardware raising a softpatch interrupt when certain TM instructions that need KVM assistance are executed in the guest. Althought some TM instructions per Power ISA are invalid forms they can raise a softpatch interrupt too. For instance, 'tresume.' instruction as defined in the ISA must have bit 31 set (1), but an instruction that matches 'tresume.' PO and XO opcode fields but has bit 31 not set (0), like 0x7cfe9ddc, also raises a softpatch interrupt. Similarly for 'treclaim.' and 'trechkpt.' instructions with bit 31 = 0, i.e. 0x7c00075c and 0x7c0007dc, respectively. Hence, if a code like the following is executed in the guest it will raise a softpatch interrupt just like a 'tresume.' when the TM facility is enabled ('tabort. 0' in the example is used only to enable the TM facility):
int main() { asm("tabort. 0; .long 0x7cfe9ddc;"); }
Currently in such a case KVM throws a complete trace like:
[345523.705984] WARNING: CPU: 24 PID: 64413 at arch/powerpc/kvm/book3s_hv_tm.c:211 kvmhv_p9_tm_emulation+0x68/0x620 [kvm_hv] [345523.705985] Modules linked in: kvm_hv(E) xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp ip6table_mangle ip6table_nat
iptable_mangle iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter bridge stp llc sch_fq_codel ipmi_powernv at24 vmx_crypto ipmi_devintf ipmi_msghandler ibmpowernv uio_pdrv_genirq kvm opal_prd uio leds_powernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables x_tables autofs4 btrfs blake2b_generic zstd_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx libcrc32c xor raid6_pq raid1 raid0 multipath linear tg3 crct10dif_vpmsum crc32c_vpmsum ipr [last unloaded: kvm_hv]
[345523.706030] CPU: 24 PID: 64413 Comm: CPU 0/KVM Tainted: G W E 5.5.0+ #1
[345523.706031] NIP: c0080000072cb9c0 LR: c0080000072b5e80 CTR: c0080000085c7850
[345523.706034] REGS: c000000399467680 TRAP: 0700 Tainted: G W E (5.5.0+)
[345523.706034] MSR: 900000010282b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE,TM[E]> CR: 24022428 XER: 00000000
[345523.706042] CFAR: c0080000072b5e7c IRQMASK: 0
GPR00: c0080000072b5e80 c000000399467910 c0080000072db500 c000000375ccc720
GPR04: c000000375ccc720 00000003fbec0000 0000a10395dda5a6 0000000000000000
GPR08: 000000007cfe9ddc 7cfe9ddc000005dc 7cfe9ddc7c0005dc c0080000072cd530
GPR12: c0080000085c7850 c0000003fffeb800 0000000000000001 00007dfb737f0000
GPR16: c0002001edcca558 0000000000000000 0000000000000000 0000000000000001
GPR20: c000000001b21258 c0002001edcca558 0000000000000018 0000000000000000
GPR24: 0000000001000000 ffffffffffffffff 0000000000000001 0000000000001500
GPR28: c0002001edcc4278 c00000037dd80000 800000050280f033 c000000375ccc720
[345523.706062] NIP [c0080000072cb9c0] kvmhv_p9_tm_emulation+0x68/0x620 [kvm_hv]
[345523.706065] LR [c0080000072b5e80] kvmppc_handle_exit_hv.isra.53+0x3e8/0x798 [kvm_hv]
[345523.706066] Call Trace:
[345523.706069] [c000000399467910] [c000000399467940] 0xc000000399467940 (unreliable)
[345523.706071] [c000000399467950] [c000000399467980] 0xc000000399467980
[345523.706075] [c0000003994679f0] [c0080000072bd1c4] kvmhv_run_single_vcpu+0xa1c/0xb80 [kvm_hv]
[345523.706079] [c000000399467ac0] [c0080000072bd8e0] kvmppc_vcpu_run_hv+0x5b8/0xb00 [kvm_hv]
[345523.706087] [c000000399467b90] [c0080000085c93cc] kvmppc_vcpu_run+0x34/0x48 [kvm]
[345523.706095] [c000000399467bb0] [c0080000085c582c] kvm_arch_vcpu_ioctl_run+0x244/0x420 [kvm]
[345523.706101] [c000000399467c40] [c0080000085b7498] kvm_vcpu_ioctl+0x3d0/0x7b0 [kvm]
[345523.706105] [c000000399467db0] [c0000000004adf9c] ksys_ioctl+0x13c/0x170
[345523.706107] [c000000399467e00] [c0000000004adff8] sys_ioctl+0x28/0x80
[345523.706111] [c000000399467e20] [c00000000000b278] system_call+0x5c/0x68
[345523.706112] Instruction dump:
[345523.706114] 419e0390 7f8a4840 409d0048 6d497c00 2f89075d 419e021c 6d497c00 2f8907dd
[345523.706119] 419e01c0 6d497c00 2f8905dd 419e00a4 <0fe00000> 38210040 38600000 ebc1fff0and then treats the executed instruction as a 'nop'.
However the POWER9 User's Manual, in section "4.6.10 Book II Invalid Forms", informs that for TM instructions bit 31 is in fact ignored, thus for the TM-related invalid forms ignoring bit 31 and handling them like the valid forms is an acceptable way to handle them. POWER8 behaves the same way too.
This commit changes the handling of the cases here described by treating the TM-related invalid forms that can generate a softpatch interrupt just like their valid forms (w/ bit 31 = 1) instead of as a 'nop' and by gently reporting any other unrecognized case to the host and treating it as illegal instruction instead of throwing a trace and treating it as a 'nop'.
--- arch/powerpc/include/asm/kvm_asm.h | 3 +++ arch/powerpc/kvm/book3s_hv_tm.c | 28 ++++++++++++++++++++----- arch/powerpc/kvm/book3s_hv_tm_builtin.c | 16 ++++++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-)
arch/powerpc/include/asm/kvm_asm.h +3 -0
@@ -150,4 +150,7 @@#define KVM_INST_FETCH_FAILED -1 +/* Extract PO and XOP opcode fields */ +#define PO_XOP_OPCODE_MASK 0xfc0007fe +#endif /* __POWERPC_KVM_ASM_H__ */
arch/powerpc/kvm/book3s_hv_tm.c +23 -5
@@ -3,6 +3,8 @@* Copyright 2017 Paul Mackerras, IBM Corp. <[email protected]> */ +#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <linux/kvm_host.h> #include <asm/kvm_ppc.h>
@@ -44,7 +46,18 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)u64 newmsr, bescr;int ra, rs; -switch (instr &0xfc0007ff ) { +/* +* rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit +* in these instructions, so masking bit 31 out doesn't change these +* instructions. For treclaim., tsr., and trechkpt. instructions if bit +* 31 = 0 then they are per ISA invalid forms, however P9 UM, in section +* 4.6.10 Book II Invalid Forms, informs specifically that ignoring bit +* 31 is an acceptable way to handle these invalid forms that have +* bit 31 = 0. Moreover, for emulation purposes both forms (w/ and wo/ +* bit 31 set) can generate a softpatch interrupt. Hence both forms +* are handled below for these instructions so they behave the same way. +*/ +switch (instr &PO_XOP_OPCODE_MASK ) {case PPC_INST_RFID :/* XXX do we need to check for PR=0 here? */ newmsr = vcpu->arch.shregs.srr1;
@@ -105,7 +118,8 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) vcpu->arch.shregs.msr = newmsr;return RESUME_GUEST ; -case PPC_INST_TSR : +/* ignore bit 31, see comment above */ +case (PPC_INST_TSR &PO_XOP_OPCODE_MASK ):/* check for PR=1 and arch 2.06 bit set in PCR */ if ((msr &MSR_PR ) && (vcpu->arch.vcore->pcr &PCR_ARCH_206 )) {/* generate an illegal instruction interrupt */
@@ -140,7 +154,8 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) vcpu->arch.shregs.msr = msr;return RESUME_GUEST ; -case PPC_INST_TRECLAIM : +/* ignore bit 31, see comment above */ +case (PPC_INST_TRECLAIM &PO_XOP_OPCODE_MASK ):/* check for TM disabled in the HFSCR or MSR */ if (!(vcpu->arch.hfscr &HFSCR_TM )) {/* generate an illegal instruction interrupt */
@@ -176,7 +191,8 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) vcpu->arch.shregs.msr &= ~MSR_TS_MASK ;return RESUME_GUEST ; -case PPC_INST_TRECHKPT : +/* ignore bit 31, see comment above */ +case (PPC_INST_TRECHKPT &PO_XOP_OPCODE_MASK ):/* XXX do we need to check for PR=0 here? */ /* check for TM disabled in the HFSCR or MSR */ if (!(vcpu->arch.hfscr &HFSCR_TM )) {
@@ -208,6 +224,8 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) }/* What should we do here? We didn't recognize the instruction */ -WARN_ON_ONCE (1 ); +kvmppc_core_queue_program (vcpu,SRR1_PROGILL ); +pr_warn_ratelimited ("Unrecognized TM-related instruction %#x for emulation" , instr); +return RESUME_GUEST ; }
arch/powerpc/kvm/book3s_hv_tm_builtin.c +14 -2
@@ -23,7 +23,18 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu)u64 newmsr, msr, bescr;int rs; -switch (instr &0xfc0007ff ) { +/* +* rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit +* in these instructions, so masking bit 31 out doesn't change these +* instructions. For the tsr. instruction if bit 31 = 0 then it is per +* ISA an invalid form, however P9 UM, in section 4.6.10 Book II Invalid +* Forms, informs specifically that ignoring bit 31 is an acceptable way +* to handle TM-related invalid forms that have bit 31 = 0. Moreover, +* for emulation purposes both forms (w/ and wo/ bit 31 set) can +* generate a softpatch interrupt. Hence both forms are handled below +* for tsr. to make them behave the same way. +*/ +switch (instr &PO_XOP_OPCODE_MASK ) {case PPC_INST_RFID :/* XXX do we need to check for PR=0 here? */ newmsr = vcpu->arch.shregs.srr1;
@@ -73,7 +84,8 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu) vcpu->arch.shregs.msr = newmsr;return 1 ; -case PPC_INST_TSR : +/* ignore bit 31, see comment above */ +case (PPC_INST_TSR &PO_XOP_OPCODE_MASK ):/* we know the MSR has the TS field = S (0b01) here */ msr = vcpu->arch.shregs.msr;/* check for PR=1 and arch 2.06 bit set in PCR */
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 175/388 drm/msm: fix leaks if initialization fails
In reply to Greg Kroah-HartmanFrom: Pavel Machek <[email protected]>
[ Upstream commit 66be340f827554cb1c8a1ed7dea97920b4085af2 ]
We should free resources in unlikely case of allocation failure.
--- drivers/gpu/drm/msm/msm_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/msm_drv.c +4 -2
@@ -444,8 +444,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)if (!dev->dma_parms) { dev->dma_parms =devm_kzalloc (dev,sizeof (*dev->dma_parms),GFP_KERNEL ); -if (!dev->dma_parms) -return -ENOMEM ; +if (!dev->dma_parms) { + ret = -ENOMEM ; + goto err_msm_uninit; + } }dma_set_max_seg_size (dev,DMA_BIT_MASK (32 ));
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 176/388 drm/msm/a5xx: Always set an OPP supported hardware value
In reply to Greg Kroah-HartmanFrom: Jordan Crouse <[email protected]>
[ Upstream commit 0478b4fc5f37f4d494245fe7bcce3f531cf380e9 ]
If the opp table specifies opp-supported-hw as a property but the driver has not set a supported hardware value the OPP subsystem will reject all the table entries.
Set a "default" value that will match the default table entries but not conflict with any possible real bin values. Also fix a small memory leak and free the buffer allocated by nvmem_cell_read().
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +20 -7
@@ -1414,18 +1414,31 @@ static const struct adreno_gpu_funcs funcs = {static void check_speed_bin (struct device *dev) {struct nvmem_cell *cell; -u32 bin, val; +u32 val; + +/* +* If the OPP table specifies a opp-supported-hw property then we have +* to set something with dev_pm_opp_set_supported_hw() or the table +* doesn't get populated so pick an arbitrary value that should +* ensure the default frequencies are selected but not conflict with any +* actual bins +*/ + val =0x80 ; cell =nvmem_cell_get (dev,"speed_bin" ); -/* If a nvmem cell isn't defined, nothing to do */ -if (IS_ERR (cell)) -return ; +if (!IS_ERR (cell)) { +void *buf =nvmem_cell_read (cell,NULL ); + +if (!IS_ERR (buf)) { +u8 bin = *((u8 *) buf); - bin = *((u32 *)nvmem_cell_read (cell,NULL )); -nvmem_cell_put (cell); + val = (1 << bin); +kfree (buf); + } - val = (1 << bin); +nvmem_cell_put (cell); + }dev_pm_opp_set_supported_hw (dev, &val,1 ); }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 177/388 tracing: Use address-of operator on section symbols
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit bf2cbe044da275021b2de5917240411a19e5c50d ]
Clang warns:
../kernel/trace/trace.c:9335:33: warning: array comparison always evaluates to true [-Wtautological-compare]
if (__stop___trace_bprintk_fmt != __start___trace_bprintk_fmt)
^1 warning generated.
These are not true arrays, they are linker defined symbols, which are just addresses. Using the address of operator silences the warning and does not change the runtime result of the check (tested with some print statements compiled in with clang + ld.lld and gcc + ld.bfd in QEMU).
--- kernel/trace/trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace.c +1 -1
@@ -9146,7 +9146,7 @@ __init static int tracer_alloc_buffers(void) goto out_free_buffer_mask;/* Only allocate trace_printk buffers if a trace_printk exists */ -if (__stop___trace_bprintk_fmt != __start___trace_bprintk_fmt) +if (&__stop___trace_bprintk_fmt != &__start___trace_bprintk_fmt)/* Must be called before global_trace.buffer is allocated */ trace_printk_init_buffers ();
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 178/388 thermal: rcar_thermal: Handle probe error gracefully
In reply to Greg Kroah-HartmanFrom: Niklas Söderlund <[email protected]>
[ Upstream commit 39056e8a989ef52486e063e34b4822b341e47b0e ]
If the common register memory resource is not available the driver needs to fail gracefully to disable PM. Instead of returning the error directly store it in ret and use the already existing error path.
--- drivers/thermal/rcar_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/thermal/rcar_thermal.c +4 -2
@@ -526,8 +526,10 @@ static int rcar_thermal_probe(struct platform_device *pdev) res =platform_get_resource (pdev,IORESOURCE_MEM , mres++); common->base =devm_ioremap_resource (dev, res); -if (IS_ERR (common->base)) -return PTR_ERR (common->base); +if (IS_ERR (common->base)) { + ret =PTR_ERR (common->base); + goto error_unregister; + } idle =0 ;/* polling delay is not needed */ }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 179/388 KVM: LAPIC: Mark hrtimer for period or oneshot mode to expire in hard interrupt context
In reply to Greg Kroah-HartmanFrom: He Zhe <[email protected]>
[ Upstream commit edec6e015a02003c2af0ce82c54ea016b5a9e3f0 ]
apic->lapic_timer.timer was initialized with HRTIMER_MODE_ABS_HARD but started later with HRTIMER_MODE_ABS, which may cause the following warning in PREEMPT_RT kernel.
WARNING: CPU: 1 PID: 2957 at kernel/time/hrtimer.c:1129 hrtimer_start_range_ns+0x348/0x3f0
CPU: 1 PID: 2957 Comm: qemu-system-x86 Not tainted 5.4.23-rt11 #1
Hardware name: Supermicro SYS-E300-9A-8C/A2SDi-8C-HLN4F, BIOS 1.1a 09/18/2018
RIP: 0010:hrtimer_start_range_ns+0x348/0x3f0
Code: 4d b8 0f 94 c1 0f b6 c9 e8 35 f1 ff ff 4c 8b 45
b0 e9 3b fd ff ff e8 d7 3f fa ff 48 98 4c 03 34
c5 a0 26 bf 93 e9 a1 fd ff ff <0f> 0b e9 fd fc ff
ff 65 8b 05 fa b7 90 6d 89 c0 48 0f a3 05 60 91
RSP: 0018:ffffbc60026ffaf8 EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffff9d81657d4110 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000006cc7987bcf RDI: ffff9d81657d4110
RBP: ffffbc60026ffb58 R08: 0000000000000001 R09: 0000000000000010
R10: 0000000000000000 R11: 0000000000000000 R12: 0000006cc7987bcf
R13: 0000000000000000 R14: 0000006cc7987bcf R15: ffffbc60026d6a00
FS: 00007f401daed700(0000) GS:ffff9d81ffa40000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000ffffffff CR3: 0000000fa7574000 CR4: 00000000003426e0
Call Trace:
? kvm_release_pfn_clean+0x22/0x60 [kvm]
start_sw_timer+0x85/0x230 [kvm]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
kvm_lapic_switch_to_sw_timer+0x72/0x80 [kvm]
vmx_pre_block+0x1cb/0x260 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_vmexit+0x1b/0x30 [kvm_intel]
? vmx_vmexit+0xf/0x30 [kvm_intel]
? vmx_sync_pir_to_irr+0x9e/0x100 [kvm_intel]
? kvm_apic_has_interrupt+0x46/0x80 [kvm]
kvm_arch_vcpu_ioctl_run+0x85b/0x1fa0 [kvm]
? _raw_spin_unlock_irqrestore+0x18/0x50
? _copy_to_user+0x2c/0x30
kvm_vcpu_ioctl+0x235/0x660 [kvm]
? rt_spin_unlock+0x2c/0x50
do_vfs_ioctl+0x3e4/0x650
? __fget+0x7a/0xa0
ksys_ioctl+0x67/0x90
__x64_sys_ioctl+0x1a/0x20
do_syscall_64+0x4d/0x120
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f4027cc54a7
Code: 00 00 90 48 8b 05 e9 59 0c 00 64 c7 00 26 00 00
00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00
00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff
73 01 c3 48 8b 0d b9 59 0c 00 f7 d8 64 89 01 48
RSP: 002b:00007f401dae9858 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00005558bd029690 RCX: 00007f4027cc54a7
RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 000000000000000d
RBP: 00007f4028b72000 R08: 00005558bc829ad0 R09: 00000000ffffffff
R10: 00005558bcf90ca0 R11: 0000000000000246 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 00005558bce1c840--[ end trace 0000000000000002 ]--
Message-Id: <[email protected]>
--- arch/x86/kvm/lapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/lapic.c +1 -1
@@ -1684,7 +1684,7 @@ static void start_sw_period(struct kvm_lapic *apic)hrtimer_start (&apic->lapic_timer.timer, apic->lapic_timer.target_expiration, -HRTIMER_MODE_ABS ); +HRTIMER_MODE_ABS_HARD ); }bool kvm_lapic_hv_timer_in_use (struct kvm_vcpu *vcpu)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 180/388 perf parse-events: Fix 3 use after frees found with clang ASAN
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit d4953f7ef1a2e87ef732823af35361404d13fea8 ]
Reproducible with a clang asan build and then running perf test in particular 'Parse event definition strings'.
--- tools/perf/util/evsel.c | 1 + tools/perf/util/parse-events.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-)
tools/perf/util/evsel.c +1 -0
@@ -1254,6 +1254,7 @@ void perf_evsel__exit(struct evsel *evsel)perf_thread_map__put (evsel->core.threads);zfree (&evsel->group_name);zfree (&evsel->name); +zfree (&evsel->pmu_name); perf_evsel__object.fini (evsel); }
tools/perf/util/parse-events.c +2 -2
@@ -1344,7 +1344,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, evsel =__add_event (list, &parse_state->idx, &attr,NULL , pmu,NULL , auto_merge_stats,NULL );if (evsel) { - evsel->pmu_name = name; + evsel->pmu_name = name ?strdup (name) :NULL ; evsel->use_uncore_alias = use_uncore_alias;return 0 ; }else {
@@ -1385,7 +1385,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, evsel->snapshot = info.snapshot; evsel->metric_expr = info.metric_expr; evsel->metric_name = info.metric_name; - evsel->pmu_name = name; + evsel->pmu_name = name ?strdup (name) :NULL ; evsel->use_uncore_alias = use_uncore_alias; evsel->percore =config_term_percore (&evsel->config_terms); }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 181/388 btrfs: do not init a reloc root if we arent relocating
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
[ Upstream commit 2abc726ab4b83db774e315c660ab8da21477092f ]
We previously were checking if the root had a dead root before accessing root->reloc_root in order to avoid a use-after-free type bug. However this scenario happens after we've unset the reloc control, so we would have been saved if we'd simply checked for fs_info->reloc_control. At this point during relocation we no longer need to be creating new reloc roots, so simply move this check above the reloc_root checks to avoid any future races and confusion.
--- fs/btrfs/relocation.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
fs/btrfs/relocation.c +16 -4
@@ -1468,6 +1468,10 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,int clear_rsv =0 ;int ret; +if (!rc || !rc->create_reloc_tree || + root->root_key.objectid ==BTRFS_TREE_RELOC_OBJECTID ) +return 0 ; +/* * The subvolume has reloc tree but the swap is finished, no need to * create/update the dead reloc tree
@@ -1481,10 +1485,6 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,return 0 ; } -if (!rc || !rc->create_reloc_tree || - root->root_key.objectid ==BTRFS_TREE_RELOC_OBJECTID ) -return 0 ; -if (!trans->reloc_reserved) { rsv = trans->block_rsv; trans->block_rsv = rc->block_rsv;
@@ -2336,6 +2336,18 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, trans =NULL ; goto out; } + +/* +* At this point we no longer have a reloc_control, so we can't +* depend on btrfs_init_reloc_root to update our last_trans. +* +* But that's ok, we started the trans handle on our +* corresponding fs_root, which means it's been added to the +* dirty list. At commit time we'll still call +* btrfs_update_reloc_root() and update our root item +* appropriately. +*/ + reloc_root->last_trans = trans->transid; trans->block_rsv = rc->block_rsv; replaced =0 ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 182/388 btrfs: free the reloc_control in a consistent way
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
[ Upstream commit 1a0afa0ecfc4dbc8d7583d03cafd3f68f781df0c ]
If we have an error while processing the reloc roots we could leak roots that were added to rc->reloc_roots before we hit the error. We could have also not removed the reloc tree mapping from our rb_tree, so clean up any remaining nodes in the reloc root rb_tree.
--- fs/btrfs/relocation.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
fs/btrfs/relocation.c +14 -2
@@ -4354,6 +4354,18 @@ static struct reloc_control *alloc_reloc_control(struct btrfs_fs_info *fs_info)return rc; } +static void free_reloc_control (struct reloc_control *rc) +{ +struct mapping_node *node, *tmp; + +free_reloc_roots (&rc->reloc_roots); +rbtree_postorder_for_each_entry_safe (node, tmp, + &rc->reloc_root_tree.rb_root, rb_node) +kfree (node); + +kfree (rc); +} +/* * Print the block group being relocated */
@@ -4486,7 +4498,7 @@ out:btrfs_dec_block_group_ro (rc->block_group);iput (rc->data_inode);btrfs_put_block_group (rc->block_group); -kfree (rc); +free_reloc_control (rc);return err; }
@@ -4659,7 +4671,7 @@ out_clean: err = ret; out_unset:unset_reloc_control (rc); -kfree (rc); +free_reloc_control (rc); out:if (!list_empty (&reloc_roots))free_reloc_roots (&reloc_roots);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 183/388 r8169: improve RTL8168b FIFO overflow workaround
In reply to Greg Kroah-HartmanFrom: Heiner Kallweit <[email protected]>
[ Upstream commit 6b02e407cbf8d421477ebb7792cd6380affcd313 ]
So far only the reset bit it set, but the handler executing the reset is not scheduled. Therefore nothing will happen until some other action schedules the handler. Improve this by ensuring that the handler is scheduled.
--- drivers/net/ethernet/realtek/r8169_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/realtek/r8169_main.c +1 -2
@@ -6256,8 +6256,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)if (unlikely (status & RxFIFOOver && tp->mac_version ==RTL_GIGA_MAC_VER_11 )) {netif_stop_queue (tp->dev); -/* XXX - Hack alert. See rtl_task(). */ -set_bit (RTL_FLAG_TASK_RESET_PENDING , tp->wk.flags); +rtl_schedule_task (tp,RTL_FLAG_TASK_RESET_PENDING ); }rtl_irq_disable (tp);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 184/388 serial: 8250_port: Dont service RX FIFO if throttled
In reply to Greg Kroah-HartmanFrom: Vignesh Raghavendra <[email protected]>
[ Upstream commit f19c3f6c8109b8bab000afd35580929958e087a9 ]
When port's throttle callback is called, it should stop pushing any more data into TTY buffer to avoid buffer overflow. This means driver has to stop HW from receiving more data and assert the HW flow control. For UARTs with auto HW flow control (such as 8250_omap) manual assertion of flow control line is not possible and only way is to allow RX FIFO to fill up, thus trigger auto HW flow control logic.
Therefore make sure that 8250 generic IRQ handler does not drain data when port is stopped (i.e UART_LSR_DR is unset in read_status_mask). Not servicing, RX FIFO would trigger auto HW flow control when FIFO occupancy reaches preset threshold, thus halting RX.
Since, error conditions in UART_LSR register are cleared just by reading the register, data has to be drained in case there are FIFO errors, else error information will lost.
--- drivers/tty/serial/8250/8250_port.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
drivers/tty/serial/8250/8250_port.c +15 -1
@@ -1816,6 +1816,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)unsigned char status;unsigned long flags;struct uart_8250_port *up =up_to_u8250p (port); +bool skip_rx = false;if (iir &UART_IIR_NO_INT )return 0 ;
@@ -1824,7 +1825,20 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status =serial_port_in (port,UART_LSR ); -if (status & (UART_LSR_DR |UART_LSR_BI )) { +/* +* If port is stopped and there are no error conditions in the +* FIFO, then don't drain the FIFO, as this may lead to TTY buffer +* overflow. Not servicing, RX FIFO would trigger auto HW flow +* control when FIFO occupancy reaches preset threshold, thus +* halting RX. This only works when auto HW flow control is +* available. +*/ +if (!(status & (UART_LSR_FIFOE |UART_LSR_BRK_ERROR_BITS )) && + (port->status & (UPSTAT_AUTOCTS |UPSTAT_AUTORTS )) && + !(port->read_status_mask &UART_LSR_DR )) + skip_rx = true; + +if (status & (UART_LSR_DR |UART_LSR_BI ) && !skip_rx) {if (!up->dma ||handle_rx_dma (up, iir)) status =serial8250_rx_chars (up, status); }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 185/388 serial: 8250_omap: Fix sleeping function called from invalid context during probe
In reply to Greg Kroah-HartmanFrom: Peter Ujfalusi <[email protected]>
[ Upstream commit 4ce35a3617c0ac758c61122b2218b6c8c9ac9398 ]
When booting j721e the following bug is printed:
[ 1.154821] BUG: sleeping function called from invalid context at kernel/sched/completion.c:99
[ 1.154827] in_atomic(): 0, irqs_disabled(): 128, non_block: 0, pid: 12, name: kworker/0:1
[ 1.154832] 3 locks held by kworker/0:1/12:
[ 1.154836] #0: ffff000840030728 ((wq_completion)events){+.+.}, at: process_one_work+0x1d4/0x6e8
[ 1.154852] #1: ffff80001214fdd8 (deferred_probe_work){+.+.}, at: process_one_work+0x1d4/0x6e8
[ 1.154860] #2: ffff00084060b170 (&dev->mutex){....}, at: __device_attach+0x38/0x138
[ 1.154872] irq event stamp: 63096
[ 1.154881] hardirqs last enabled at (63095): [<ffff800010b74318>] _raw_spin_unlock_irqrestore+0x70/0x78
[ 1.154887] hardirqs last disabled at (63096): [<ffff800010b740d8>] _raw_spin_lock_irqsave+0x28/0x80
[ 1.154893] softirqs last enabled at (62254): [<ffff800010080c88>] _stext+0x488/0x564
[ 1.154899] softirqs last disabled at (62247): [<ffff8000100fdb3c>] irq_exit+0x114/0x140
[ 1.154906] CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.6.0-rc6-next-20200318-00094-g45e4089b0bd3 #221
[ 1.154911] Hardware name: Texas Instruments K3 J721E SoC (DT)
[ 1.154917] Workqueue: events deferred_probe_work_func
[ 1.154923] Call trace:
[ 1.154928] dump_backtrace+0x0/0x190
[ 1.154933] show_stack+0x14/0x20
[ 1.154940] dump_stack+0xe0/0x148
[ 1.154946] ___might_sleep+0x150/0x1f0
[ 1.154952] __might_sleep+0x4c/0x80
[ 1.154957] wait_for_completion_timeout+0x40/0x140
[ 1.154964] ti_sci_set_device_state+0xa0/0x158
[ 1.154969] ti_sci_cmd_get_device_exclusive+0x14/0x20
[ 1.154977] ti_sci_dev_start+0x34/0x50
[ 1.154984] genpd_runtime_resume+0x78/0x1f8
[ 1.154991] __rpm_callback+0x3c/0x140
[ 1.154996] rpm_callback+0x20/0x80
[ 1.155001] rpm_resume+0x568/0x758
[ 1.155007] __pm_runtime_resume+0x44/0xb0
[ 1.155013] omap8250_probe+0x2b4/0x508
[ 1.155019] platform_drv_probe+0x50/0xa0
[ 1.155023] really_probe+0xd4/0x318
[ 1.155028] driver_probe_device+0x54/0xe8
[ 1.155033] __device_attach_driver+0x80/0xb8
[ 1.155039] bus_for_each_drv+0x74/0xc0
[ 1.155044] __device_attach+0xdc/0x138
[ 1.155049] device_initial_probe+0x10/0x18
[ 1.155053] bus_probe_device+0x98/0xa0
[ 1.155058] deferred_probe_work_func+0x74/0xb0
[ 1.155063] process_one_work+0x280/0x6e8
[ 1.155068] worker_thread+0x48/0x430
[ 1.155073] kthread+0x108/0x138
[ 1.155079] ret_from_fork+0x10/0x18To fix the bug we need to first call pm_runtime_enable() prior to any pm_runtime calls.
--- drivers/tty/serial/8250/8250_omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/8250/8250_omap.c +1 -1
@@ -1234,6 +1234,7 @@ static int omap8250_probe(struct platform_device *pdev)spin_lock_init (&priv->rx_dma_lock);device_init_wakeup (&pdev->dev, true); +pm_runtime_enable (&pdev->dev);pm_runtime_use_autosuspend (&pdev->dev);/*
@@ -1247,7 +1248,6 @@ static int omap8250_probe(struct platform_device *pdev)pm_runtime_set_autosuspend_delay (&pdev->dev,-1 );pm_runtime_irq_safe (&pdev->dev); -pm_runtime_enable (&pdev->dev);pm_runtime_get_sync (&pdev->dev);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 186/388 serial: 8250: 8250_omap: Terminate DMA before pushing data on RX timeout
In reply to Greg Kroah-HartmanFrom: Vignesh Raghavendra <[email protected]>
[ Upstream commit 7cf4df30a98175033e9849f7f16c46e96ba47f41 ]
Terminate and flush DMA internal buffers, before pushing RX data to higher layer. Otherwise, this will lead to data corruption, as driver would end up pushing stale buffer data to higher layer while actual data is still stuck inside DMA hardware and has yet not arrived at the memory.
While at that, replace deprecated dmaengine_terminate_all() with dmaengine_terminate_async().
--- drivers/tty/serial/8250/8250_omap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/tty/serial/8250/8250_omap.c +4 -2
@@ -790,7 +790,10 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)dmaengine_tx_status (dma->rxchan, dma->rx_cookie, &state); count = dma->rx_size - state.residue; - +if (count < dma->rx_size) +dmaengine_terminate_async (dma->rxchan); +if (!count) + goto unlock; ret =tty_insert_flip_string (tty_port, dma->rx_buf, count); p->port.icount.rx += ret;
@@ -852,7 +855,6 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)spin_unlock_irqrestore (&priv->rx_dma_lock, flags);__dma_rx_do_complete (p); -dmaengine_terminate_all (dma->rxchan); }static int omap_8250_rx_dma (struct uart_8250_port *p)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 187/388 perf cpumap: Fix snprintf overflow check
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit d74b181a028bb5a468f0c609553eff6a8fdf4887 ]
'snprintf' returns the number of characters which would be generated for the given input.
If the returned value is *greater than* or equal to the buffer size, it means that the output has been truncated.
Fix the overflow test accordingly.
--- tools/perf/util/cpumap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
tools/perf/util/cpumap.c +5 -5
@@ -299,7 +299,7 @@ static void set_max_cpu_num(void)/* get the highest possible cpu number for a sparse allocation */ ret =snprintf (path,PATH_MAX ,"%s/devices/system/cpu/possible" , mnt); -if (ret =PATH_MAX ) { +if (ret >=PATH_MAX ) {pr_err ("sysfs path crossed PATH_MAX(%d) size\n" ,PATH_MAX ); goto out; }
@@ -310,7 +310,7 @@ static void set_max_cpu_num(void)/* get the highest present cpu number for a sparse allocation */ ret =snprintf (path,PATH_MAX ,"%s/devices/system/cpu/present" , mnt); -if (ret =PATH_MAX ) { +if (ret >=PATH_MAX ) {pr_err ("sysfs path crossed PATH_MAX(%d) size\n" ,PATH_MAX ); goto out; }
@@ -338,7 +338,7 @@ static void set_max_node_num(void)/* get the highest possible cpu number for a sparse allocation */ ret =snprintf (path,PATH_MAX ,"%s/devices/system/node/possible" , mnt); -if (ret =PATH_MAX ) { +if (ret >=PATH_MAX ) {pr_err ("sysfs path crossed PATH_MAX(%d) size\n" ,PATH_MAX ); goto out; }
@@ -423,7 +423,7 @@ int cpu__setup_cpunode_map(void)return 0 ; n =snprintf (path,PATH_MAX ,"%s/devices/system/node" , mnt); -if (n =PATH_MAX ) { +if (n >=PATH_MAX ) {pr_err ("sysfs path crossed PATH_MAX(%d) size\n" ,PATH_MAX );return -1 ; }
@@ -438,7 +438,7 @@ int cpu__setup_cpunode_map(void)continue ; n =snprintf (buf,PATH_MAX ,"%s/%s" , path, dent1->d_name); -if (n =PATH_MAX ) { +if (n >=PATH_MAX ) {pr_err ("sysfs path crossed PATH_MAX(%d) size\n" ,PATH_MAX );continue ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 188/388 net: axienet: Convert DMA error handler to a work queue
In reply to Greg Kroah-HartmanFrom: Andre Przywara <[email protected]>
[ Upstream commit 24201a64770afe2e17050b2ab9e8c0e24e9c23b2 ]
The DMA error handler routine is currently a tasklet, scheduled to run after the DMA error IRQ was handled.
However it needs to take the MDIO mutex, which is not allowed to do in a tasklet. A kernel (with debug options) complains consequently:
[ 614.050361] net eth0: DMA Tx error 0x174019
[ 614.064002] net eth0: Current BD is at: 0x8f84aa0ce
[ 614.080195] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:935
[ 614.109484] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 40, name: kworker/u4:4
[ 614.135428] 3 locks held by kworker/u4:4/40:
[ 614.149075] #0: ffff000879863328 ((wq_completion)rpciod){....}, at: process_one_work+0x1f0/0x6a8
[ 614.177528] #1: ffff80001251bdf8 ((work_completion)(&task->u.tk_work)){....}, at: process_one_work+0x1f0/0x6a8
[ 614.209033] #2: ffff0008784e0110 (sk_lock-AF_INET-RPC){....}, at: tcp_sendmsg+0x24/0x58
[ 614.235429] CPU: 0 PID: 40 Comm: kworker/u4:4 Not tainted 5.6.0-rc3-00926-g4a165a9d5921 #26
[ 614.260854] Hardware name: ARM Test FPGA (DT)
[ 614.274734] Workqueue: rpciod rpc_async_schedule
[ 614.289022] Call trace:
[ 614.296871] dump_backtrace+0x0/0x1a0
[ 614.308311] show_stack+0x14/0x20
[ 614.318751] dump_stack+0xbc/0x100
[ 614.329403] ___might_sleep+0xf0/0x140
[ 614.341018] __might_sleep+0x4c/0x80
[ 614.352201] __mutex_lock+0x5c/0x8a8
[ 614.363348] mutex_lock_nested+0x1c/0x28
[ 614.375654] axienet_dma_err_handler+0x38/0x388
[ 614.389999] tasklet_action_common.isra.15+0x160/0x1a8
[ 614.405894] tasklet_action+0x24/0x30
[ 614.417297] efi_header_end+0xe0/0x494
[ 614.429020] irq_exit+0xd0/0xd8
[ 614.439047] __handle_domain_irq+0x60/0xb0
[ 614.451877] gic_handle_irq+0xdc/0x2d0
[ 614.463486] el1_irq+0xcc/0x180
[ 614.473451] __tcp_transmit_skb+0x41c/0xb58
[ 614.486513] tcp_write_xmit+0x224/0x10a0
[ 614.498792] __tcp_push_pending_frames+0x38/0xc8
[ 614.513126] tcp_rcv_established+0x41c/0x820
[ 614.526301] tcp_v4_do_rcv+0x8c/0x218
[ 614.537784] __release_sock+0x5c/0x108
[ 614.549466] release_sock+0x34/0xa0
[ 614.560318] tcp_sendmsg+0x40/0x58
[ 614.571053] inet_sendmsg+0x40/0x68
[ 614.582061] sock_sendmsg+0x18/0x30
[ 614.593074] xs_sendpages+0x218/0x328
[ 614.604506] xs_tcp_send_request+0xa0/0x1b8
[ 614.617461] xprt_transmit+0xc8/0x4f0
[ 614.628943] call_transmit+0x8c/0xa0
[ 614.640028] __rpc_execute+0xbc/0x6f8
[ 614.651380] rpc_async_schedule+0x28/0x48
[ 614.663846] process_one_work+0x298/0x6a8
[ 614.676299] worker_thread+0x40/0x490
[ 614.687687] kthread+0x134/0x138
[ 614.697804] ret_from_fork+0x10/0x18
[ 614.717319] xilinx_axienet 7fe00000.ethernet eth0: Link is Down
[ 615.748343] xilinx_axienet 7fe00000.ethernet eth0: Link is Up - 1Gbps/Full - flow control offSince tasklets are not really popular anymore anyway, lets convert this over to a work queue, which can sleep and thus can take the MDIO mutex.
--- drivers/net/ethernet/xilinx/xilinx_axienet.h | 2 +- .../net/ethernet/xilinx/xilinx_axienet_main.c | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-)
drivers/net/ethernet/xilinx/xilinx_axienet.h +1 -1
@@ -435,7 +435,7 @@ struct axienet_local {void __iomem *regs;void __iomem *dma_regs; -struct tasklet_struct dma_err_tasklet; +struct work_struct dma_err_task;int tx_irq;int rx_irq;
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +12 -12
@@ -806,7 +806,7 @@ static irqreturn_t axienet_tx_irq(int irq, void *_ndev)/* Write to the Rx channel control register */ axienet_dma_out32 (lp,XAXIDMA_RX_CR_OFFSET , cr); -tasklet_schedule (&lp->dma_err_tasklet); +schedule_work (&lp->dma_err_task);axienet_dma_out32 (lp,XAXIDMA_TX_SR_OFFSET , status); } out:
@@ -855,7 +855,7 @@ static irqreturn_t axienet_rx_irq(int irq, void *_ndev)/* write to the Rx channel control register */ axienet_dma_out32 (lp,XAXIDMA_RX_CR_OFFSET , cr); -tasklet_schedule (&lp->dma_err_tasklet); +schedule_work (&lp->dma_err_task);axienet_dma_out32 (lp,XAXIDMA_RX_SR_OFFSET , status); } out:
@@ -891,7 +891,7 @@ static irqreturn_t axienet_eth_irq(int irq, void *_ndev)return IRQ_HANDLED ; } -static void axienet_dma_err_handler (unsigned long data); +static void axienet_dma_err_handler (struct work_struct *work);/** * axienet_open - Driver open routine.
@@ -935,9 +935,8 @@ static int axienet_open(struct net_device *ndev)phylink_start (lp->phylink); -/* Enable tasklets for Axi DMA error handling */ -tasklet_init (&lp->dma_err_tasklet, axienet_dma_err_handler, - (unsigned long ) lp); +/* Enable worker thread for Axi DMA error handling */ +INIT_WORK (&lp->dma_err_task, axienet_dma_err_handler);/* Enable interrupts for Axi DMA Tx */ ret = request_irq(lp->tx_irq, axienet_tx_irq, IRQF_SHARED,
@@ -966,7 +965,7 @@ err_rx_irq: err_tx_irq:phylink_stop (lp->phylink);phylink_disconnect_phy (lp->phylink); -tasklet_kill (&lp->dma_err_tasklet); +cancel_work_sync (&lp->dma_err_task);dev_err (lp->dev,"request_irq() failed\n" );return ret; }
@@ -1025,7 +1024,7 @@ static int axienet_stop(struct net_device *ndev)axienet_mdio_enable (lp);mutex_unlock (&lp->mii_bus->mdio_lock); -tasklet_kill (&lp->dma_err_tasklet); +cancel_work_sync (&lp->dma_err_task);if (lp->eth_irq >0 )free_irq (lp->eth_irq, ndev);
@@ -1505,17 +1504,18 @@ static const struct phylink_mac_ops axienet_phylink_ops = { };/** -* axienet_dma_err_handler - Tasklet handler for Axi DMA Error -* @data: Data passed +* axienet_dma_err_handler - Work queue task for Axi DMA Error +* @work: pointer to work_struct * * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the * Tx/Rx BDs. */ -static void axienet_dma_err_handler (unsigned long data) +static void axienet_dma_err_handler (struct work_struct *work) {u32 axienet_status;u32 cr, i; -struct axienet_local *lp = (struct axienet_local *) data; + struct axienet_local *lp = container_of(work, struct axienet_local, + dma_err_task);struct net_device *ndev = lp->ndev;struct axidma_bd *cur_p;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 189/388 net: axienet: Propagate failure of DMA descriptor setup
In reply to Greg Kroah-HartmanFrom: Andre Przywara <[email protected]>
[ Upstream commit ee44d0b78839b21591501424fd3cb3648cc803b5 ]
When we fail allocating the DMA buffers in axienet_dma_bd_init(), we report this error, but carry on with initialisation nevertheless.
This leads to a kernel panic when the driver later wants to send a packet, as it uses uninitialised data structures.
Make the axienet_device_reset() routine return an error value, as it contains the DMA buffer initialisation. Make sure we propagate the error up the chain and eventually fail the driver initialisation, to avoid relying on non-initialised buffers.
--- .../net/ethernet/xilinx/xilinx_axienet_main.c | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-)
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +19 -7
@@ -437,9 +437,10 @@ static void axienet_setoptions(struct net_device *ndev, u32 options) lp->options |= options; } -static void __axienet_device_reset (struct axienet_local *lp) +static int __axienet_device_reset (struct axienet_local *lp) {u32 timeout; +/* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset * process of Axi DMA takes a while to complete as all pending * commands/transfers will be flushed or completed during this
@@ -455,9 +456,11 @@ static void __axienet_device_reset(struct axienet_local *lp)if (--timeout ==0 ) {netdev_err (lp->ndev,"%s: DMA reset timeout!\n" , __func__); -break ; +return -ETIMEDOUT ; } } + +return 0 ; }/**
@@ -470,13 +473,17 @@ static void __axienet_device_reset(struct axienet_local *lp)* areconnected to Axi Ethernet reset lines, this in turn resets the Axi * Ethernet core. No separate hardware reset is done for the Axi Ethernet * core. +* Returns 0 on success or a negative error number otherwise. */ -static void axienet_device_reset (struct net_device *ndev) +static int axienet_device_reset (struct net_device *ndev) {u32 axienet_status;struct axienet_local *lp =netdev_priv (ndev); +int ret; -__axienet_device_reset (lp); + ret =__axienet_device_reset (lp); +if (ret) +return ret; lp->max_frm_size =XAE_MAX_VLAN_FRAME_SIZE ; lp->options |=XAE_OPTION_VLAN ;
@@ -491,9 +498,11 @@ static void axienet_device_reset(struct net_device *ndev) lp->options |=XAE_OPTION_JUMBO ; } -if (axienet_dma_bd_init (ndev)) { + ret =axienet_dma_bd_init (ndev); +if (ret) {netdev_err (ndev,"%s: descriptor allocation failed\n" , __func__); +return ret; } axienet_status =axienet_ior (lp,XAE_RCW1_OFFSET );
@@ -518,6 +527,8 @@ static void axienet_device_reset(struct net_device *ndev)axienet_setoptions (ndev, lp->options);netif_trans_update (ndev); + +return 0 ; }/**
@@ -921,8 +932,9 @@ static int axienet_open(struct net_device *ndev)*/ mutex_lock (&lp->mii_bus->mdio_lock);axienet_mdio_disable (lp); -axienet_device_reset (ndev); - ret =axienet_mdio_enable (lp); + ret =axienet_device_reset (ndev); +if (ret ==0 ) + ret =axienet_mdio_enable (lp);mutex_unlock (&lp->mii_bus->mdio_lock);if (ret <0 )return ret;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 190/388 cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_work_fn
In reply to Greg Kroah-HartmanFrom: Pratik Rajesh Sampat <[email protected]>
[ Upstream commit d95fe371ecd28901f11256c610b988ed44e36ee2 ]
The patch avoids allocating cpufreq_policy on stack hence fixing frame size overflow in 'powernv_cpufreq_work_fn'
--- drivers/cpufreq/powernv-cpufreq.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/cpufreq/powernv-cpufreq.c +8 -5
@@ -902,6 +902,7 @@ static struct notifier_block powernv_cpufreq_reboot_nb = {void powernv_cpufreq_work_fn (struct work_struct *work) { struct chip *chip = container_of(work, struct chip, throttle); +struct cpufreq_policy *policy;unsigned int cpu;cpumask_t mask;
@@ -916,12 +917,14 @@ void powernv_cpufreq_work_fn(struct work_struct *work) chip->restore = false;for_each_cpu (cpu, &mask) {int index; -struct cpufreq_policy policy; -cpufreq_get_policy (&policy, cpu); - index =cpufreq_table_find_index_c (&policy, policy.cur); -powernv_cpufreq_target_index (&policy, index); -cpumask_andnot (&mask, &mask, policy.cpus); + policy =cpufreq_cpu_get (cpu); +if (!policy) +continue ; + index =cpufreq_table_find_index_c (policy, policy->cur); +powernv_cpufreq_target_index (policy, index); +cpumask_andnot (&mask, &mask, policy->cpus); +cpufreq_cpu_put (policy); } out:put_online_cpus ();
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 191/388 tools: gpio-hammer: Avoid potential overflow in main
In reply to Greg Kroah-HartmanFrom: Gabriel Ravier <[email protected]>
[ Upstream commit d1ee7e1f5c9191afb69ce46cc7752e4257340a31 ]
If '-o' was used more than 64 times in a single invocation of gpio-hammer, this could lead to an overflow of the 'lines' array. This commit fixes this by avoiding the overflow and giving a proper diagnostic back to the user
--- tools/gpio/gpio-hammer.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
tools/gpio/gpio-hammer.c +16 -1
@@ -135,7 +135,14 @@ int main(int argc, char **argv) device_name = optarg;break ;case 'o' : - lines[i] =strtoul (optarg,NULL ,10 ); +/* +* Avoid overflow. Do not immediately error, we want to +* be able to accurately report on the amount of times +* '-o' was given to give an accurate error message +*/ +if (i <GPIOHANDLES_MAX ) + lines[i] =strtoul (optarg,NULL ,10 ); + i++;break ;case '?' :
@@ -143,6 +150,14 @@ int main(int argc, char **argv)return -1 ; } } + +if (i >=GPIOHANDLES_MAX ) { +fprintf (stderr, +"Only %d occurences of '-o' are allowed, %d were found\n" , +GPIOHANDLES_MAX , i +1 ); +return -1 ; + } + nlines = i;if (!device_name || !nlines) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 192/388 exec: Add exec_update_mutex to replace cred_guard_mutex
In reply to Greg Kroah-HartmanFrom: Eric W. Biederman <[email protected]>
[ Upstream commit eea9673250db4e854e9998ef9da6d4584857f0ea ]
The cred_guard_mutex is problematic as it is held over possibly indefinite waits for userspace. The possible indefinite waits for userspace that I have identified are: The cred_guard_mutex is held in PTRACE_EVENT_EXIT waiting for the tracer. The cred_guard_mutex is held over "put_user(0, tsk->clear_child_tid)" in exit_mm(). The cred_guard_mutex is held over "get_user(futex_offset, ...") in exit_robust_list. The cred_guard_mutex held over copy_strings.
The functions get_user and put_user can trigger a page fault which can potentially wait indefinitely in the case of userfaultfd or if userspace implements part of the page fault path.
In any of those cases the userspace process that the kernel is waiting for might make a different system call that winds up taking the cred_guard_mutex and result in deadlock.
Holding a mutex over any of those possibly indefinite waits for userspace does not appear necessary. Add exec_update_mutex that will just cover updating the process during exec where the permissions and the objects pointed to by the task struct may be out of sync.
The plan is to switch the users of cred_guard_mutex to exec_update_mutex one by one. This lets us move forward while still being careful and not introducing any regressions.
Ref: 45c1a159b85b ("Add PTRACE_O_TRACEVFORKDONE and PTRACE_O_TRACEEXIT facilities.")
Ref: 456f17cd1a28 ("[PATCH] user-vm-unlock-2.5.31-A2")
--- fs/exec.c | 22 +++++++++++++++++++--- include/linux/binfmts.h | 8 +++++++- include/linux/sched/signal.h | 9 ++++++++- init/init_task.c | 1 + kernel/fork.c | 1 + 5 files changed, 36 insertions(+), 5 deletions(-)
fs/exec.c +19 -3
@@ -1007,16 +1007,26 @@ ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) }EXPORT_SYMBOL (read_code); +/* +* Maps the mm_struct mm into the current task struct. +* On success, this function returns with the mutex +* exec_update_mutex locked. +*/ static int exec_mmap (struct mm_struct *mm) {struct task_struct *tsk;struct mm_struct *old_mm, *active_mm; +int ret;/* Notify parent that we're no longer interested in the old VM */ tsk = current; old_mm = current->mm;exec_mm_release (tsk, old_mm); + ret =mutex_lock_killable (&tsk->signal->exec_update_mutex); +if (ret) +return ret; +if (old_mm) {sync_mm_rss (old_mm);/*
@@ -1028,9 +1038,11 @@ static int exec_mmap(struct mm_struct *mm)down_read (&old_mm->mmap_sem);if (unlikely (old_mm->core_state)) {up_read (&old_mm->mmap_sem); +mutex_unlock (&tsk->signal->exec_update_mutex);return -EINTR ; } } +task_lock (tsk); active_mm = tsk->active_mm;membarrier_exec_mmap (mm);
@@ -1285,11 +1297,12 @@ int flush_old_exec(struct linux_binprm * bprm) goto out;/* -* After clearing bprm->mm (to mark that current is using the -* prepared mm now), we have nothing left of the original +* After setting bprm->called_exec_mmap (to mark that current is +* using the prepared mm now), we have nothing left of the original * process. If anything from here on returns an error, the check * in search_binary_handler() will SEGV current. */ + bprm->called_exec_mmap =1 ; bprm->mm =NULL ;set_fs (USER_DS );
@@ -1423,6 +1436,8 @@ static void free_bprm(struct linux_binprm *bprm) {free_arg_pages (bprm);if (bprm->cred) { +if (bprm->called_exec_mmap) +mutex_unlock (¤t->signal->exec_update_mutex);mutex_unlock (¤t->signal->cred_guard_mutex);abort_creds (bprm->cred); }
@@ -1472,6 +1487,7 @@ void install_exec_creds(struct linux_binprm *bprm)* credentials; any time after this it may be unlocked. */ security_bprm_committed_creds (bprm); +mutex_unlock (¤t->signal->exec_update_mutex);mutex_unlock (¤t->signal->cred_guard_mutex); }EXPORT_SYMBOL (install_exec_creds);
@@ -1663,7 +1679,7 @@ int search_binary_handler(struct linux_binprm *bprm)read_lock (&binfmt_lock);put_binfmt (fmt); -if (retval <0 && !bprm->mm) { +if (retval <0 && bprm->called_exec_mmap) {/* we got to flush_old_exec() and failed after it */ read_unlock (&binfmt_lock);force_sigsegv (SIGSEGV );
include/linux/binfmts.h +7 -1
@@ -44,7 +44,13 @@ struct linux_binprm {* exec has happened. Used to sanitize execution environment * and to set AT_SECURE auxv for glibc. */ - secureexec:1 ; + secureexec:1 , +/* +* Set by flush_old_exec, when exec_mmap has been called. +* This is past the point of no return, when the +* exec_update_mutex has been taken. +*/ + called_exec_mmap:1;#ifdef __alpha__ unsigned int taso:1;#endif
include/linux/sched/signal.h +8 -1
@@ -224,7 +224,14 @@ struct signal_struct {struct mutex cred_guard_mutex;/* guard against foreign influences on * credential calculations -* (notably. ptrace) */ +* (notably. ptrace) +* Deprecated do not use in new code. +* Use exec_update_mutex instead. +*/ +struct mutex exec_update_mutex;/* Held while task_struct is being +* updated during exec, and may have +* inconsistent permissions. +*/ } __randomize_layout;/*
init/init_task.c +1 -0
@@ -26,6 +26,7 @@ static struct signal_struct init_signals = { .multiprocess = HLIST_HEAD_INIT, .rlim = INIT_RLIMITS, .cred_guard_mutex = __MUTEX_INITIALIZER(init_signals.cred_guard_mutex), + .exec_update_mutex =__MUTEX_INITIALIZER (init_signals.exec_update_mutex), #ifdef CONFIG_POSIX_TIMERS .posix_timers =LIST_HEAD_INIT (init_signals.posix_timers), .cputimer = {
kernel/fork.c +1 -0
@@ -1586,6 +1586,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) sig->oom_score_adj_min = current->signal->oom_score_adj_min;mutex_init (&sig->cred_guard_mutex); +mutex_init (&sig->exec_update_mutex);return 0 ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 193/388 exec: Fix a deadlock in strace
In reply to Greg Kroah-HartmanFrom: Bernd Edlinger <[email protected]>
[ Upstream commit 3e74fabd39710ee29fa25618d2c2b40cfa7d76c7 ]
This fixes a deadlock in the tracer when tracing a multi-threaded application that calls execve while more than one thread are running.
I observed that when running strace on the gcc test suite, it always blocks after a while, when expect calls execve, because other threads have to be terminated. They send ptrace events, but the strace is no longer able to respond, since it is blocked in vm_access.
The deadlock is always happening when strace needs to access the tracees process mmap, while another thread in the tracee starts to execve a child process, but that cannot continue until the PTRACE_EVENT_EXIT is handled and the WIFEXITED event is received:
strace D 0 30614 30584 0x00000000
Call Trace: __schedule+0x3ce/0x6e0 schedule+0x5c/0xd0 schedule_preempt_disabled+0x15/0x20 __mutex_lock.isra.13+0x1ec/0x520 __mutex_lock_killable_slowpath+0x13/0x20 mutex_lock_killable+0x28/0x30 mm_access+0x27/0xa0 process_vm_rw_core.isra.3+0xff/0x550 process_vm_rw+0xdd/0xf0 __x64_sys_process_vm_readv+0x31/0x40 do_syscall_64+0x64/0x220 entry_SYSCALL_64_after_hwframe+0x44/0xa9
expect D 0 31933 30876 0x80004003
Call Trace: __schedule+0x3ce/0x6e0 schedule+0x5c/0xd0 flush_old_exec+0xc4/0x770 load_elf_binary+0x35a/0x16c0 search_binary_handler+0x97/0x1d0 __do_execve_file.isra.40+0x5d4/0x8a0 __x64_sys_execve+0x49/0x60 do_syscall_64+0x64/0x220 entry_SYSCALL_64_after_hwframe+0x44/0xa9
This changes mm_access to use the new exec_update_mutex instead of cred_guard_mutex.
This patch is based on the following patch by Eric W. Biederman:
"[PATCH 0/5] Infrastructure to allow fixing exec deadlocks"
--- kernel/fork.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/fork.c +2 -2
@@ -1221,7 +1221,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)struct mm_struct *mm;int err; - err =mutex_lock_killable (&task->signal->cred_guard_mutex); + err =mutex_lock_killable (&task->signal->exec_update_mutex);if (err)return ERR_PTR (err);
@@ -1231,7 +1231,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)mmput (mm); mm =ERR_PTR (-EACCES ); } -mutex_unlock (&task->signal->cred_guard_mutex); +mutex_unlock (&task->signal->exec_update_mutex);return mm; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 194/388 selftests/ptrace: add test cases for dead-locks
In reply to Greg Kroah-HartmanFrom: Bernd Edlinger <[email protected]>
[ Upstream commit 2de4e82318c7f9d34f4b08599a612cd4cd10bf0b ]
This adds test cases for ptrace deadlocks.
Additionally fixes a compile problem in get_syscall_info.c, observed with gcc-4.8.4:
get_syscall_info.c: In function 'get_syscall_info':
get_syscall_info.c:93:3: error: 'for' loop initial declarations are only
allowed in C99 mode
for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) {
^
get_syscall_info.c:93:3: note: use option -std=c99 or -std=gnu99 to compile
your code
--- tools/testing/selftests/ptrace/Makefile | 4 +- tools/testing/selftests/ptrace/vmaccess.c | 86 +++++++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/ptrace/vmaccess.c
tools/testing/selftests/ptrace/Makefile +2 -2
@@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -CFLAGS += -iquote../../../../include/uapi -Wall +CFLAGS += -std=c99 -pthread -iquote../../../../include/uapi -Wall -TEST_GEN_PROGS := get_syscall_info peeksiginfo +TEST_GEN_PROGS := get_syscall_info peeksiginfo vmaccess include ../lib.mk
tools/testing/selftests/ptrace/vmaccess.c new file +86 -0
86 lines not on this page · raw message
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 195/388 kernel/kcmp.c: Use new infrastructure to fix deadlocks in execve
In reply to Greg Kroah-HartmanFrom: Bernd Edlinger <[email protected]>
[ Upstream commit 454e3126cb842388e22df6b3ac3da44062c00765 ]
This changes kcmp_epoll_target to use the new exec_update_mutex instead of cred_guard_mutex.
This should be safe, as the credentials are only used for reading, and furthermore ->mm and ->sighand are updated on execve, but only under the new exec_update_mutex.
--- kernel/kcmp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/kcmp.c +4 -4
@@ -173,8 +173,8 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,/* * One should have enough rights to inspect task details. */ - ret =kcmp_lock (&task1->signal->cred_guard_mutex, - &task2->signal->cred_guard_mutex); + ret =kcmp_lock (&task1->signal->exec_update_mutex, + &task2->signal->exec_update_mutex);if (ret) goto err; if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) ||
@@ -229,8 +229,8 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type, } err_unlock: -kcmp_unlock (&task1->signal->cred_guard_mutex, - &task2->signal->cred_guard_mutex); +kcmp_unlock (&task1->signal->exec_update_mutex, + &task2->signal->exec_update_mutex); err:put_task_struct (task1);put_task_struct (task2);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 196/388 proc: Use new infrastructure to fix deadlocks in execve
In reply to Greg Kroah-HartmanFrom: Bernd Edlinger <[email protected]>
[ Upstream commit 2db9dbf71bf98d02a0bf33e798e5bfd2a9944696 ]
This changes lock_trace to use the new exec_update_mutex instead of cred_guard_mutex.
This fixes possible deadlocks when the trace is accessing /proc/$pid/stack for instance.
This should be safe, as the credentials are only used for reading, and task->mm is updated on execve under the new exec_update_mutex.
--- fs/proc/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/proc/base.c +3 -3
@@ -403,11 +403,11 @@ print0:static int lock_trace (struct task_struct *task) { -int err =mutex_lock_killable (&task->signal->cred_guard_mutex); +int err =mutex_lock_killable (&task->signal->exec_update_mutex);if (err)return err;if (!ptrace_may_access (task,PTRACE_MODE_ATTACH_FSCREDS )) { -mutex_unlock (&task->signal->cred_guard_mutex); +mutex_unlock (&task->signal->exec_update_mutex);return -EPERM ; }return 0 ;
@@ -415,7 +415,7 @@ static int lock_trace(struct task_struct *task)static void unlock_trace (struct task_struct *task) { -mutex_unlock (&task->signal->cred_guard_mutex); +mutex_unlock (&task->signal->exec_update_mutex); }#ifdef CONFIG_STACKTRACE
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 197/388 proc: io_accounting: Use new infrastructure to fix deadlocks in execve
In reply to Greg Kroah-HartmanFrom: Bernd Edlinger <[email protected]>
[ Upstream commit 76518d3798855242817e8a8ed76b2d72f4415624 ]
This changes do_io_accounting to use the new exec_update_mutex instead of cred_guard_mutex.
This fixes possible deadlocks when the trace is accessing /proc/$pid/io for instance.
This should be safe, as the credentials are only used for reading.
--- fs/proc/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/proc/base.c +2 -2
@@ -2770,7 +2770,7 @@ static int do_io_accounting(struct task_struct *task, struct seq_file *m, int whunsigned long flags;int result; - result =mutex_lock_killable (&task->signal->cred_guard_mutex); + result =mutex_lock_killable (&task->signal->exec_update_mutex);if (result)return result;
@@ -2806,7 +2806,7 @@ static int do_io_accounting(struct task_struct *task, struct seq_file *m, int wh result =0 ; out_unlock: -mutex_unlock (&task->signal->cred_guard_mutex); +mutex_unlock (&task->signal->exec_update_mutex);return result; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 198/388 perf: Use new infrastructure to fix deadlocks in execve
In reply to Greg Kroah-HartmanFrom: Bernd Edlinger <[email protected]>
[ Upstream commit 6914303824bb572278568330d72fc1f8f9814e67 ]
This changes perf_event_set_clock to use the new exec_update_mutex instead of cred_guard_mutex.
This should be safe, as the credentials are only used for reading.
--- kernel/events/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/events/core.c +6 -6
@@ -1253,7 +1253,7 @@ static void put_ctx(struct perf_event_context *ctx)* function. * * Lock order: -* cred_guard_mutex +* exec_update_mutex * task_struct::perf_event_mutex * perf_event_context::mutex * perf_event::child_mutex;
@@ -11002,14 +11002,14 @@ SYSCALL_DEFINE5(perf_event_open, }if (task) { - err =mutex_lock_interruptible (&task->signal->cred_guard_mutex); + err =mutex_lock_interruptible (&task->signal->exec_update_mutex);if (err) goto err_task;/* * Reuse ptrace permission checks for now. * -* We must hold cred_guard_mutex across this and any potential +* We must hold exec_update_mutex across this and any potential * perf_install_in_context() call for this new event to * serialize against exec() altering our credentials (and the * perf_event_exit_task() that could imply).
@@ -11298,7 +11298,7 @@ SYSCALL_DEFINE5(perf_event_open,mutex_unlock (&ctx->mutex);if (task) { -mutex_unlock (&task->signal->cred_guard_mutex); +mutex_unlock (&task->signal->exec_update_mutex);put_task_struct (task); }
@@ -11334,7 +11334,7 @@ err_alloc:free_event (event); err_cred:if (task) -mutex_unlock (&task->signal->cred_guard_mutex); +mutex_unlock (&task->signal->exec_update_mutex); err_task:if (task)put_task_struct (task);
@@ -11639,7 +11639,7 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)/* * When a child task exits, feed back event values to parent events. * -* Can be called with cred_guard_mutex held when called from +* Can be called with exec_update_mutex held when called from * install_exec_creds(). */ void perf_event_exit_task (struct task_struct *child)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 199/388 nvme-multipath: do not reset on unknown status
In reply to Greg Kroah-HartmanFrom: John Meneghini <[email protected]>
[ Upstream commit 764e9332098c0e60251386a507fe46ac91276120 ]
The nvme multipath error handling defaults to controller reset if the error is unknown. There are, however, no existing nvme status codes that indicate a reset should be used, and resetting causes unnecessary disruption to the rest of IO.
Change nvme's error handling to first check if failover should happen. If not, let the normal error handling take over rather than reset the controller.
--- drivers/nvme/host/core.c | 5 +---- drivers/nvme/host/multipath.c | 21 +++++++++------------ drivers/nvme/host/nvme.h | 5 +++-- 3 files changed, 13 insertions(+), 18 deletions(-)
drivers/nvme/host/core.c +1 -4
@@ -288,11 +288,8 @@ void nvme_complete_rq(struct request *req)nvme_req (req)->ctrl->comp_seen = true;if (unlikely (status !=BLK_STS_OK &&nvme_req_needs_retry (req))) { -if ((req->cmd_flags &REQ_NVME_MPATH ) && -blk_path_error (status)) { -nvme_failover_req (req); +if ((req->cmd_flags &REQ_NVME_MPATH ) &&nvme_failover_req (req))return ; - }if (!blk_queue_dying (req->q)) {nvme_retry_req (req);
drivers/nvme/host/multipath.c +9 -12
@@ -65,17 +65,12 @@ void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns, } } -void nvme_failover_req (struct request *req) +bool nvme_failover_req (struct request *req) {struct nvme_ns *ns = req->q->queuedata;u16 status =nvme_req (req)->status;unsigned long flags; -spin_lock_irqsave (&ns->head->requeue_lock, flags); -blk_steal_bios (&ns->head->requeue_list, req); -spin_unlock_irqrestore (&ns->head->requeue_lock, flags); -blk_mq_end_request (req,0 ); -switch (status &0x7ff ) {case NVME_SC_ANA_TRANSITION :case NVME_SC_ANA_INACCESSIBLE :
@@ -104,15 +99,17 @@ void nvme_failover_req(struct request *req)nvme_mpath_clear_current_path (ns);break ;default : -/* -* Reset the controller for any non-ANA error as we don't know -* what caused the error. -*/ -nvme_reset_ctrl (ns->ctrl); -break ; +/* This was a non-ANA error so follow the normal error path. */ +return false; } +spin_lock_irqsave (&ns->head->requeue_lock, flags); +blk_steal_bios (&ns->head->requeue_list, req); +spin_unlock_irqrestore (&ns->head->requeue_lock, flags); +blk_mq_end_request (req,0 ); +kblockd_schedule_work (&ns->head->requeue_work); +return true; }void nvme_kick_requeue_lists (struct nvme_ctrl *ctrl)
drivers/nvme/host/nvme.h +3 -2
@@ -530,7 +530,7 @@ void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);void nvme_mpath_start_freeze (struct nvme_subsystem *subsys);void nvme_set_disk_name (char *disk_name,struct nvme_ns *ns,struct nvme_ctrl *ctrl,int *flags); -void nvme_failover_req (struct request *req); +bool nvme_failover_req (struct request *req);void nvme_kick_requeue_lists (struct nvme_ctrl *ctrl);int nvme_mpath_alloc_disk (struct nvme_ctrl *ctrl,struct nvme_ns_head *head);void nvme_mpath_add_disk (struct nvme_ns *ns,struct nvme_id_ns *id);
@@ -579,8 +579,9 @@ static inline void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,sprintf (disk_name,"nvme%dn%d" , ctrl->instance, ns->head->instance); } -static inline void nvme_failover_req (struct request *req) +static inline bool nvme_failover_req (struct request *req) { +return false; }static inline void nvme_kick_requeue_lists (struct nvme_ctrl *ctrl) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 200/388 nvme: Fix ctrl use-after-free during sysfs deletion
In reply to Greg Kroah-HartmanFrom: Israel Rukshin <[email protected]>
[ Upstream commit b780d7415aacec855e2f2370cbf98f918b224903 ]
In case nvme_sysfs_delete() is called by the user before taking the ctrl reference count, the ctrl may be freed during the creation and cause the bug. Take the reference as soon as the controller is externally visible, which is done by cdev_device_add() in nvme_init_ctrl(). Also take the reference count at the core layer instead of taking it on each transport separately.
--- drivers/nvme/host/core.c | 2 ++ drivers/nvme/host/fc.c | 4 +--- drivers/nvme/host/pci.c | 1 - drivers/nvme/host/rdma.c | 3 +-- drivers/nvme/host/tcp.c | 3 +-- drivers/nvme/target/loop.c | 3 +-- 6 files changed, 6 insertions(+), 10 deletions(-)
drivers/nvme/host/core.c +2 -0
@@ -4082,6 +4082,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,if (ret) goto out_release_instance; +nvme_get_ctrl (ctrl);cdev_init (&ctrl->cdev, &nvme_dev_fops); ctrl->cdev.owner = ops->module; ret =cdev_device_add (&ctrl->cdev, ctrl->device);
@@ -4100,6 +4101,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,return 0 ; out_free_name: +nvme_put_ctrl (ctrl);kfree_const (ctrl->device->kobj.name); out_release_instance:ida_simple_remove (&nvme_instance_ida, ctrl->instance);
drivers/nvme/host/fc.c +1 -3
@@ -3171,10 +3171,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, goto fail_ctrl; } -nvme_get_ctrl (&ctrl->ctrl); -if (!queue_delayed_work (nvme_wq, &ctrl->connect_work,0 )) { -nvme_put_ctrl (&ctrl->ctrl);dev_err (ctrl->ctrl.device,"NVME-FC{%d}: failed to schedule initial connect\n" , ctrl->cnum);
@@ -3199,6 +3196,7 @@ fail_ctrl:/* initiate nvme ctrl ref counting teardown */ nvme_uninit_ctrl (&ctrl->ctrl); +nvme_put_ctrl (&ctrl->ctrl);/* Remove core ctrl ref. */ nvme_put_ctrl (&ctrl->ctrl);
drivers/nvme/host/pci.c +0 -1
@@ -2850,7 +2850,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)dev_info (dev->ctrl.device,"pci function %s\n" ,dev_name (&pdev->dev));nvme_reset_ctrl (&dev->ctrl); -nvme_get_ctrl (&dev->ctrl);async_schedule (nvme_async_probe, dev);return 0 ;
drivers/nvme/host/rdma.c +1 -2
@@ -2088,8 +2088,6 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,dev_info (ctrl->ctrl.device,"new ctrl: NQN \"%s\", addr %pISpcs\n" , ctrl->ctrl.opts->subsysnqn, &ctrl->addr); -nvme_get_ctrl (&ctrl->ctrl); -mutex_lock (&nvme_rdma_ctrl_mutex);list_add_tail (&ctrl->list, &nvme_rdma_ctrl_list);mutex_unlock (&nvme_rdma_ctrl_mutex);
@@ -2099,6 +2097,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, out_uninit_ctrl:nvme_uninit_ctrl (&ctrl->ctrl);nvme_put_ctrl (&ctrl->ctrl); +nvme_put_ctrl (&ctrl->ctrl);if (ret >0 ) ret = -EIO ;return ERR_PTR (ret);
drivers/nvme/host/tcp.c +1 -2
@@ -2404,8 +2404,6 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,dev_info (ctrl->ctrl.device,"new ctrl: NQN \"%s\", addr %pISp\n" , ctrl->ctrl.opts->subsysnqn, &ctrl->addr); -nvme_get_ctrl (&ctrl->ctrl); -mutex_lock (&nvme_tcp_ctrl_mutex);list_add_tail (&ctrl->list, &nvme_tcp_ctrl_list);mutex_unlock (&nvme_tcp_ctrl_mutex);
@@ -2415,6 +2413,7 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev, out_uninit_ctrl:nvme_uninit_ctrl (&ctrl->ctrl);nvme_put_ctrl (&ctrl->ctrl); +nvme_put_ctrl (&ctrl->ctrl);if (ret >0 ) ret = -EIO ;return ERR_PTR (ret);
drivers/nvme/target/loop.c +1 -2
@@ -619,8 +619,6 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,dev_info (ctrl->ctrl.device,"new ctrl: \"%s\"\n" , ctrl->ctrl.opts->subsysnqn); -nvme_get_ctrl (&ctrl->ctrl); - changed =nvme_change_ctrl_state (&ctrl->ctrl,NVME_CTRL_LIVE );WARN_ON_ONCE (!changed);
@@ -638,6 +636,7 @@ out_free_queues:kfree (ctrl->queues); out_uninit_ctrl:nvme_uninit_ctrl (&ctrl->ctrl); +nvme_put_ctrl (&ctrl->ctrl); out_put_ctrl:nvme_put_ctrl (&ctrl->ctrl);if (ret >0 )
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 201/388 nvme: Fix controller creation races with teardown flow
In reply to Greg Kroah-HartmanFrom: Israel Rukshin <[email protected]>
[ Upstream commit ce1518139e6976cf19c133b555083354fdb629b8 ]
Calling nvme_sysfs_delete() when the controller is in the middle of creation may cause several bugs. If the controller is in NEW state we remove delete_controller file and don't delete the controller. The user will not be able to use nvme disconnect command on that controller again, although the controller may be active. Other bugs may happen if the controller is in the middle of create_ctrl callback and nvme_do_delete_ctrl() starts. For example, freeing I/O tagset at nvme_do_delete_ctrl() before it was allocated at create_ctrl callback.
To fix all those races don't allow the user to delete the controller before it was fully created.
--- drivers/nvme/host/core.c | 5 +++++ drivers/nvme/host/nvme.h | 1 + 2 files changed, 6 insertions(+)
drivers/nvme/host/core.c +5 -0
@@ -3197,6 +3197,10 @@ static ssize_t nvme_sysfs_delete(struct device *dev, {struct nvme_ctrl *ctrl =dev_get_drvdata (dev); +/* Can't delete non-created controllers */ +if (!ctrl->created) +return -EBUSY ; +if (device_remove_file_self (dev, attr))nvme_delete_ctrl_sync (ctrl);return count;
@@ -3992,6 +3996,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)nvme_queue_scan (ctrl);nvme_start_queues (ctrl); } + ctrl->created = true; }EXPORT_SYMBOL_GPL (nvme_start_ctrl);
drivers/nvme/host/nvme.h +1 -0
@@ -253,6 +253,7 @@ struct nvme_ctrl {struct nvme_command ka_cmd;struct work_struct fw_act_work;unsigned long events; +bool created;#ifdef CONFIG_NVME_MULTIPATH /* asymmetric namespace access: */
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 202/388 brcmfmac: Fix double freeing in the fmac usb data path
In reply to Greg Kroah-HartmanFrom: Raveendran Somu <[email protected]>
[ Upstream commit 78179869dc3f5c0059bbf5d931a2717f1ad97ecd ]
When the brcmf_fws_process_skb() fails to get hanger slot for queuing the skb, it tries to free the skb.
But the caller brcmf_netdev_start_xmit() of that funciton frees the packet on error return value.
This causes the double freeing and which caused the kernel crash.
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +1 -2
@@ -2149,8 +2149,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)brcmf_fws_enq (fws,BRCMF_FWS_SKBSTATE_DELAYED , fifo, skb);brcmf_fws_schedule_deq (fws); }else { -bphy_err (drvr,"drop skb: no hanger slot\n" ); -brcmf_txfinalize (ifp, skb, false); +bphy_err (drvr,"no hanger slot available\n" ); rc = -ENOMEM ; }brcmf_fws_unlock (fws);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 203/388 xfs: prohibit fs freezing when using empty transactions
In reply to Greg Kroah-HartmanFrom: Darrick J. Wong <[email protected]>
[ Upstream commit 27fb5a72f50aa770dd38b0478c07acacef97e3e7 ]
I noticed that fsfreeze can take a very long time to freeze an XFS if there happens to be a GETFSMAP caller running in the background. I also happened to notice the following in dmesg:
------------[ cut here ]------------ WARNING: CPU: 2 PID: 43492 at fs/xfs/xfs_super.c:853 xfs_quiesce_attr+0x83/0x90 [xfs] Modules linked in: xfs libcrc32c ip6t_REJECT nf_reject_ipv6 ipt_REJECT nf_reject_ipv4 ip_set_hash_ip ip_set_hash_net xt_tcpudp xt_set ip_set_hash_mac ip_set nfnetlink ip6table_filter ip6_tables bfq iptable_filter sch_fq_codel ip_tables x_tables nfsv4 af_packet [last unloaded: xfs] CPU: 2 PID: 43492 Comm: xfs_io Not tainted 5.6.0-rc4-djw #rc4 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.10.2-1ubuntu1 04/01/2014 RIP: 0010:xfs_quiesce_attr+0x83/0x90 [xfs] Code: 7c 07 00 00 85 c0 75 22 48 89 df 5b e9 96 c1 00 00 48 c7 c6 b0 2d 38 a0 48 89 df e8 57 64 ff ff 8b 83 7c 07 00 00 85 c0 74 de <0f> 0b 48 89 df 5b e9 72 c1 00 00 66 90 0f 1f 44 00 00 41 55 41 54 RSP: 0018:ffffc900030f3e28 EFLAGS: 00010202 RAX: 0000000000000001 RBX: ffff88802ac54000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff81e4a6f0 RDI: 00000000ffffffff RBP: ffff88807859f070 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000010 R12: 0000000000000000 R13: ffff88807859f388 R14: ffff88807859f4b8 R15: ffff88807859f5e8 FS: 00007fad1c6c0fc0(0000) GS:ffff88807e000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f0c7d237000 CR3: 0000000077f01003 CR4: 00000000001606a0 Call Trace: xfs_fs_freeze+0x25/0x40 [xfs] freeze_super+0xc8/0x180 do_vfs_ioctl+0x70b/0x750 ? __fget_files+0x135/0x210 ksys_ioctl+0x3a/0xb0 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x50/0x1a0 entry_SYSCALL_64_after_hwframe+0x49/0xbe
These two things appear to be related. The assertion trips when another thread initiates a fsmap request (which uses an empty transaction) after the freezer waited for m_active_trans to hit zero but before the the freezer executes the WARN_ON just prior to calling xfs_log_quiesce.
The lengthy delays in freezing happen because the freezer calls xfs_wait_buftarg to clean out the buffer lru list. Meanwhile, the GETFSMAP caller is continuing to grab and release buffers, which means that it can take a very long time for the buffer lru list to empty out.
We fix both of these races by calling sb_start_write to obtain freeze protection while using empty transactions for GETFSMAP and for metadata scrubbing. The other two users occur during mount, during which time we cannot fs freeze.
--- fs/xfs/scrub/scrub.c | 9 +++++++++ fs/xfs/xfs_fsmap.c | 9 +++++++++ fs/xfs/xfs_trans.c | 5 +++++ 3 files changed, 23 insertions(+)
fs/xfs/scrub/scrub.c +9 -0
@@ -167,6 +167,7 @@ xchk_teardown(xfs_irele (sc->ip); sc->ip =NULL ; } +sb_end_write (sc->mp->m_super);if (sc->flags &XCHK_REAPING_DISABLED )xchk_start_reaping (sc);if (sc->flags &XCHK_HAS_QUOTAOFFLOCK ) {
@@ -489,6 +490,14 @@ xfs_scrub_metadata( sc.ops = &meta_scrub_ops[sm->sm_type]; sc.sick_mask =xchk_health_mask_for_scrub_type (sm->sm_type); retry_op: +/* +* If freeze runs concurrently with a scrub, the freeze can be delayed +* indefinitely as we walk the filesystem and iterate over metadata +* buffers. Freeze quiesces the log (which waits for the buffer LRU to +* be emptied) and that won't happen while checking is running. +*/ +sb_start_write (mp->m_super); +/* Set up for the operation. */ error = sc.ops->setup (&sc, ip);if (error)
fs/xfs/xfs_fsmap.c +9 -0
@@ -895,6 +895,14 @@ xfs_getfsmap( info.format_arg = arg; info.head = head; +/* +* If fsmap runs concurrently with a scrub, the freeze can be delayed +* indefinitely as we walk the rmapbt and iterate over metadata +* buffers. Freeze quiesces the log (which waits for the buffer LRU to +* be emptied) and that won't happen while we're reading buffers. +*/ +sb_start_write (mp->m_super); +/* For each device we support... */ for (i =0 ; i <XFS_GETFSMAP_DEVS ; i++) {/* Is this device within the range the user asked for? */
@@ -934,6 +942,7 @@ xfs_getfsmap(if (tp)xfs_trans_cancel (tp); +sb_end_write (mp->m_super); head->fmh_oflags =FMH_OF_DEV_T ;return error; }
fs/xfs/xfs_trans.c +5 -0
@@ -306,6 +306,11 @@ xfs_trans_alloc(* * Note the zero-length reservation; this transaction MUST be cancelled * without any dirty data. +* +* Callers should obtain freeze protection to avoid two conflicts with fs +* freezing: (1) having active transactions trip the m_active_trans ASSERTs; +* and (2) grabbing buffers at the same time that freeze is trying to drain +* the buffer LRU list. */ int xfs_trans_alloc_empty(
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 204/388 RDMA/rxe: Set sys_image_guid to be aligned with HW IB devices
In reply to Greg Kroah-HartmanFrom: Zhu Yanjun <[email protected]>
[ Upstream commit d0ca2c35dd15a3d989955caec02beea02f735ee6 ]
The RXE driver doesn't set sys_image_guid and user space applications see zeros. This causes to pyverbs tests to fail with the following traceback, because the IBTA spec requires to have valid sys_image_guid.
Traceback (most recent call last):
File "./tests/test_device.py", line 51, in test_query_device
self.verify_device_attr(attr)
File "./tests/test_device.py", line 74, in verify_device_attr
assert attr.sys_image_guid != 0
In order to fix it, set sys_image_guid to be equal to node_guid.
Before:
5: rxe0: ... node_guid 5054:00ff:feaa:5363 sys_image_guid 0000:0000:0000:0000
After:
5: rxe0: ... node_guid 5054:00ff:feaa:5363 sys_image_guid 5054:00ff:feaa:5363
--- drivers/infiniband/sw/rxe/rxe.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/infiniband/sw/rxe/rxe.c +2 -0
@@ -118,6 +118,8 @@ static void rxe_init_device_param(struct rxe_dev *rxe) rxe->attr.max_fast_reg_page_list_len =RXE_MAX_FMR_PAGE_LIST_LEN ; rxe->attr.max_pkeys =RXE_MAX_PKEYS ; rxe->attr.local_ca_ack_delay =RXE_LOCAL_CA_ACK_DELAY ; +addrconf_addr_eui48 ((unsigned char *)&rxe->attr.sys_image_guid, + rxe->ndev->dev_addr); rxe->max_ucontext =RXE_MAX_UCONTEXT ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 205/388 IB/iser: Always check sig MR before putting it to the free pool
In reply to Greg Kroah-HartmanFrom: Sergey Gorenko <[email protected]>
[ Upstream commit 26e28deb813eed908cf31a6052870b6493ec0e86 ]
libiscsi calls the check_protection transport handler only if SCSI-Respose is received. So, the handler is never called if iSCSI task is completed for some other reason like a timeout or error handling. And this behavior looks correct. But the iSER does not handle this case properly because it puts a non-checked signature MR to the free pool. Then the error occurs at reusing the MR because it is not allowed to invalidate a signature MR without checking.
This commit adds an extra check to iser_unreg_mem_fastreg(), which is a part of the task cleanup flow. Now the signature MR is checked there if it is needed.
--- drivers/infiniband/ulp/iser/iser_memory.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
drivers/infiniband/ulp/iser/iser_memory.c +18 -3
@@ -292,12 +292,27 @@ void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task, {struct iser_device *device = iser_task->iser_conn->ib_conn.device;struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir]; +struct iser_fr_desc *desc; +struct ib_mr_status mr_status; -if (!reg->mem_h) + desc = reg->mem_h; +if (!desc)return ; - device->reg_ops->reg_desc_put (&iser_task->iser_conn->ib_conn, - reg->mem_h); +/* +* The signature MR cannot be invalidated and reused without checking. +* libiscsi calls the check_protection transport handler only if +* SCSI-Response is received. And the signature MR is not checked if +* the task is completed for some other reason like a timeout or error +* handling. That's why we must check the signature MR here before +* putting it to the free pool. +*/ +if (unlikely (desc->sig_protected)) { + desc->sig_protected = false; +ib_check_mr_status (desc->rsc.sig_mr,IB_MR_CHECK_SIG_STATUS , + &mr_status); + } + device->reg_ops->reg_desc_put (&iser_task->iser_conn->ib_conn, desc); reg->mem_h =NULL ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 206/388 scsi: hpsa: correct race condition in offload enabled
In reply to Greg Kroah-HartmanFrom: Don Brace <[email protected]>
[ Upstream commit 3e16e83a62edac7617bfd8dbb4e55d04ff6adbe1 ]
Correct race condition where ioaccel is re-enabled before the raid_map is updated. For RAID_1, RAID_1ADM, and RAID 5/6 there is a BUG_ON called which is bad.
- Change event thread to disable ioaccel only. Send all requests down the RAID path instead.
- Have rescan thread handle offload_enable.
- Since there is only one rescan allowed at a time, turning offload_enabled on/off should not be racy. Each handler queues up a rescan if one is already in progress.
- For timing diagram, offload_enabled is initially off due to a change (transformation: splitmirror/remirror), ...
otbe = offload_to_be_enabled
oe = offload_enabled
Time Event Rescan Completion Request
Worker Worker Thread Thread
---- ------ ------ ---------- -------
T0 | | + UA |
T1 | + rescan started | 0x3f |
T2 + Event | | 0x0e |
T3 + Ack msg | | |
T4 | + if (!dev[i]->oe && | |
T5 | | dev[i]->otbe) | |
T6 | | get_raid_map | |
T7 + otbe = 1 | | |
T8 | | | |
T9 | + oe = otbe | |
T10 | | | + ioaccel request
T11 * BUG_ON T0 - I/O completion with UA 0x3f 0x0e sets rescan flag. T1 - rescan worker thread starts a rescan.
T2 - event comes in
T3 - event thread starts and issues "Acknowledge" message
...
T6 - rescan thread has bypassed code to reload new raid map.
...
T7 - event thread runs and sets offload_to_be_enabled
...
T9 - rescan thread turns on offload_enabled.
T10- request comes in and goes down ioaccel path. T11- BUG_ON.
- After the patch is applied, ioaccel_enabled can only be re-enabled in the re-scan thread.
--- drivers/scsi/hpsa.c | 80 ++++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 23 deletions(-)
drivers/scsi/hpsa.c +57 -23
@@ -504,6 +504,12 @@ static ssize_t host_store_rescan(struct device *dev,return count; } +static void hpsa_turn_off_ioaccel_for_device (struct hpsa_scsi_dev_t *device) +{ + device->offload_enabled =0 ; + device->offload_to_be_enabled =0 ; +} +static ssize_t host_show_firmware_revision (struct device *dev,struct device_attribute *attr,char *buf) {
@@ -1738,8 +1744,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, __func__, h->scsi_host->host_no, logical_drive->bus, logical_drive->target, logical_drive->lun); - logical_drive->offload_enabled =0 ; - logical_drive->offload_to_be_enabled =0 ; +hpsa_turn_off_ioaccel_for_device (logical_drive); logical_drive->queue_depth =8 ; } }
@@ -2499,8 +2504,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h, IOACCEL2_SERV_RESPONSE_FAILURE) {if (c2->error_data.status ==IOACCEL2_STATUS_SR_IOACCEL_DISABLED ) { - dev->offload_enabled =0 ; - dev->offload_to_be_enabled =0 ; +hpsa_turn_off_ioaccel_for_device (dev); }if (dev->in_reset) {
@@ -3670,10 +3674,17 @@ static void hpsa_get_ioaccel_status(struct ctlr_info *h, this_device->offload_config = !!(ioaccel_status &OFFLOAD_CONFIGURED_BIT );if (this_device->offload_config) { - this_device->offload_to_be_enabled = +bool offload_enabled = !!(ioaccel_status &OFFLOAD_ENABLED_BIT ); -if (hpsa_get_raid_map (h, scsi3addr, this_device)) - this_device->offload_to_be_enabled =0 ; +/* +* Check to see if offload can be enabled. +*/ +if (offload_enabled) { + rc =hpsa_get_raid_map (h, scsi3addr, this_device); +if (rc)/* could not load raid_map */ + goto out; + this_device->offload_to_be_enabled =1 ; + } } out:
@@ -3996,8 +4007,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, }else { this_device->raid_level =RAID_UNKNOWN ; this_device->offload_config =0 ; - this_device->offload_enabled =0 ; - this_device->offload_to_be_enabled =0 ; +hpsa_turn_off_ioaccel_for_device (this_device); this_device->hba_ioaccel_enabled =0 ; this_device->volume_offline =0 ; this_device->queue_depth = h->nr_cmds;
@@ -5230,8 +5240,12 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,/* Handles load balance across RAID 1 members. * (2-drive R1 and R10 with even # of drives.) * Appropriate for SSDs, not optimal for HDDs +* Ensure we have the correct raid_map. */ -BUG_ON (le16_to_cpu (map->layout_map_count) !=2 ); +if (le16_to_cpu (map->layout_map_count) !=2 ) { +hpsa_turn_off_ioaccel_for_device (dev); +return IO_ACCEL_INELIGIBLE ; + }if (dev->offload_to_mirror) map_index +=le16_to_cpu (map->data_disks_per_row); dev->offload_to_mirror = !dev->offload_to_mirror;
@@ -5239,8 +5253,12 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,case HPSA_RAID_ADM :/* Handles N-way mirrors (R1-ADM) * and R10 with # of drives divisible by 3.) +* Ensure we have the correct raid_map. */ -BUG_ON (le16_to_cpu (map->layout_map_count) !=3 ); +if (le16_to_cpu (map->layout_map_count) !=3 ) { +hpsa_turn_off_ioaccel_for_device (dev); +return IO_ACCEL_INELIGIBLE ; + } offload_to_mirror = dev->offload_to_mirror; raid_map_helper(map, offload_to_mirror,
@@ -5265,7 +5283,10 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, r5or6_blocks_per_row =le16_to_cpu (map->strip_size) *le16_to_cpu (map->data_disks_per_row); -BUG_ON (r5or6_blocks_per_row ==0 ); +if (r5or6_blocks_per_row ==0 ) { +hpsa_turn_off_ioaccel_for_device (dev); +return IO_ACCEL_INELIGIBLE ; + } stripesize = r5or6_blocks_per_row *le16_to_cpu (map->layout_map_count);#if BITS_PER_LONG ==32
@@ -8285,7 +8306,7 @@ static int detect_controller_lockup(struct ctlr_info *h)* * Called from monitor controller worker (hpsa_event_monitor_worker) * -* A Volume (or Volumes that comprise an Array set may be undergoing a +* A Volume (or Volumes that comprise an Array set) may be undergoing a * transformation, so we will be turning off ioaccel for all volumes that * make up the Array. */
@@ -8308,6 +8329,9 @@ static void hpsa_set_ioaccel_status(struct ctlr_info *h)* Run through current device list used during I/O requests. */ for (i =0 ; i < h->ndevices; i++) { +int offload_to_be_enabled =0 ; +int offload_config =0 ; + device = h->dev[i];if (!device)
@@ -8325,25 +8349,35 @@ static void hpsa_set_ioaccel_status(struct ctlr_info *h)continue ; ioaccel_status = buf[IOACCEL_STATUS_BYTE ]; - device->offload_config = + +/* +* Check if offload is still configured on +*/ + offload_config = !!(ioaccel_status &OFFLOAD_CONFIGURED_BIT ); -if (device->offload_config) - device->offload_to_be_enabled = +/* +* If offload is configured on, check to see if ioaccel +* needs to be enabled. +*/ +if (offload_config) + offload_to_be_enabled = !!(ioaccel_status &OFFLOAD_ENABLED_BIT ); +/* +* If ioaccel is to be re-enabled, re-enable later during the +* scan operation so the driver can get a fresh raidmap +* before turning ioaccel back on. +*/ +if (offload_to_be_enabled) +continue ; +/* * Immediately turn off ioaccel for any volume the * controller tells us to. Some of the reasons could be: * transformation - change to the LVs of an Array. * degraded volume - component failure -* -* If ioaccel is to be re-enabled, re-enable later during the -* scan operation so the driver can get a fresh raidmap -* before turning ioaccel back on. -* */ -if (!device->offload_to_be_enabled) - device->offload_enabled =0 ; +hpsa_turn_off_ioaccel_for_device (device); }kfree (buf);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 207/388 SUNRPC: Fix a potential buffer overflow in svc_print_xprts()
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit b25b60d7bfb02a74bc3c2d998e09aab159df8059 ]
'maxlen' is the total size of the destination buffer. There is only one caller and this value is 256.
When we compute the size already used and what we would like to add in the buffer, the trailling NULL character is not taken into account. However, this trailling character will be added by the 'strcat' once we have checked that we have enough place.
So, there is a off-by-one issue and 1 byte of the stack could be erroneously overwridden.
Take into account the trailling NULL, when checking if there is enough place in the destination buffer.
While at it, also replace a 'sprintf' by a safer 'snprintf', check for output truncation and avoid a superfluous 'strlen'.
[ cel: very minor fix to documenting comment
--- net/sunrpc/svc_xprt.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
net/sunrpc/svc_xprt.c +14 -5
@@ -104,8 +104,17 @@ void svc_unreg_xprt_class(struct svc_xprt_class *xcl) }EXPORT_SYMBOL_GPL (svc_unreg_xprt_class); -/* -* Format the transport list for printing +/** +* svc_print_xprts - Format the transport list for printing +* @buf: target buffer for formatted address +* @maxlen: length of target buffer +* +* Fills in @buf with a string containing a list of transport names, each name +* terminated with '\n'. If the buffer is too small, some entries may be +* missing, but it is guaranteed that all lines in the output buffer are +* complete. +* +* Returns positive length of the filled-in string. */ int svc_print_xprts (char *buf,int maxlen) {
@@ -118,9 +127,9 @@ int svc_print_xprts(char *buf, int maxlen)list_for_each_entry (xcl, &svc_xprt_class_list, xcl_list) {int slen; -sprintf (tmpstr,"%s %d\n" , xcl->xcl_name, xcl->xcl_max_payload); - slen =strlen (tmpstr); -if (len + slen > maxlen) + slen =snprintf (tmpstr,sizeof (tmpstr),"%s %d\n" , + xcl->xcl_name, xcl->xcl_max_payload); +if (slen >=sizeof (tmpstr) || len + slen >= maxlen)break ; len += slen;strcat (buf, tmpstr);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 208/388 svcrdma: Fix leak of transport addresses
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 1a33d8a284b1e85e03b8c7b1ea8fb985fccd1d71 ]
Kernel memory leak detected:
unreferenced object 0xffff888849cdf480 (size 8):
comm "kworker/u8:3", pid 2086, jiffies 4297898756 (age 4269.856s) hex dump (first 8 bytes):
30 00 cd 49 88 88 ff ff 0..I....
backtrace:
[<00000000acfc370b>] __kmalloc_track_caller+0x137/0x183
[<00000000a2724354>] kstrdup+0x2b/0x43
[<0000000082964f84>] xprt_rdma_format_addresses+0x114/0x17d [rpcrdma]
[<00000000dfa6ed00>] xprt_setup_rdma_bc+0xc0/0x10c [rpcrdma]
[<0000000073051a83>] xprt_create_transport+0x3f/0x1a0 [sunrpc]
[<0000000053531a8e>] rpc_create+0x118/0x1cd [sunrpc]
[<000000003a51b5f8>] setup_callback_client+0x1a5/0x27d [nfsd]
[<000000001bd410af>] nfsd4_process_cb_update.isra.7+0x16c/0x1ac [nfsd]
[<000000007f4bbd56>] nfsd4_run_cb_work+0x4c/0xbd [nfsd]
[<0000000055c5586b>] process_one_work+0x1b2/0x2fe
[<00000000b1e3e8ef>] worker_thread+0x1a6/0x25a
[<000000005205fb78>] kthread+0xf6/0xfb
[<000000006d2dc057>] ret_from_fork+0x3a/0x50Introduce a call to xprt_rdma_free_addresses() similar to the way that the TCP backchannel releases a transport's peer address strings.
--- net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 1 + 1 file changed, 1 insertion(+)
net/sunrpc/xprtrdma/svc_rdma_backchannel.c +1 -0
@@ -252,6 +252,7 @@ xprt_rdma_bc_put(struct rpc_xprt *xprt) {dprintk ("svcrdma: %s: xprt %p\n" , __func__, xprt); +xprt_rdma_free_addresses (xprt);xprt_free (xprt); }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 209/388 netfilter: nf_tables: silence a RCU-list warning in nft_table_lookup()
In reply to Greg Kroah-HartmanFrom: Qian Cai <[email protected]>
[ Upstream commit 0a6a9515fe390976cd762c52d8d4f446d7a14285 ]
It is safe to traverse &net->nft.tables with &net->nft.commit_mutex held using list_for_each_entry_rcu(). Silence the PROVE_RCU_LIST false positive,
WARNING: suspicious RCU usagenet/netfilter/nf_tables_api.c:523 RCU-list traversed in non-reader section!!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
1 lock held by iptables/1384:
#0: ffffffff9745c4a8 (&net->nft.commit_mutex){+.+.}, at: nf_tables_valid_genid+0x25/0x60 [nf_tables]
Call Trace: dump_stack+0xa1/0xea lockdep_rcu_suspicious+0x103/0x10d nft_table_lookup.part.0+0x116/0x120 [nf_tables] nf_tables_newtable+0x12c/0x7d0 [nf_tables] nfnetlink_rcv_batch+0x559/0x1190 [nfnetlink] nfnetlink_rcv+0x1da/0x210 [nfnetlink] netlink_unicast+0x306/0x460 netlink_sendmsg+0x44b/0x770 ____sys_sendmsg+0x46b/0x4a0 ___sys_sendmsg+0x138/0x1a0 __sys_sendmsg+0xb6/0x130 __x64_sys_sendmsg+0x48/0x50 do_syscall_64+0x69/0xf4 entry_SYSCALL_64_after_hwframe+0x49/0xb3
--- net/netfilter/nf_tables_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +2 -1
@@ -456,7 +456,8 @@ static struct nft_table *nft_table_lookup(const struct net *net,if (nla ==NULL )return ERR_PTR (-EINVAL ); -list_for_each_entry_rcu (table, &net->nft.tables, list) { +list_for_each_entry_rcu (table, &net->nft.tables, list, +lockdep_is_held (&net->nft.commit_mutex)) {if (!nla_strcmp (nla, table->name) && table->family == family &&nft_active_genmask (table, genmask))
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 210/388 PCI: Use ioremap(), not phys_to_virt() for platform ROM
In reply to Greg Kroah-HartmanFrom: Mikel Rychliski <[email protected]>
[ Upstream commit 72e0ef0e5f067fd991f702f0b2635d911d0cf208 ]
On some EFI systems, the video BIOS is provided by the EFI firmware. The boot stub code stores the physical address of the ROM image in pdev->rom. Currently we attempt to access this pointer using phys_to_virt(), which doesn't work with CONFIG_HIGHMEM.
On these systems, attempting to load the radeon module on a x86_32 kernel can result in the following:
BUG: unable to handle page fault for address: 3e8ed03c #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP CPU: 0 PID: 317 Comm: systemd-udevd Not tainted 5.6.0-rc3-next-20200228 #2 Hardware name: Apple Computer, Inc. MacPro1,1/Mac-F4208DC8, BIOS MP11.88Z.005C.B08.0707021221 07/02/07 EIP: radeon_get_bios+0x5ed/0xe50 [radeon] Code: 00 00 84 c0 0f 85 12 fd ff ff c7 87 64 01 00 00 00 00 00 00 8b 47 08 8b 55 b0 e8 1e 83 e1 d6 85 c0 74 1a 8b 55 c0 85 d2 74 13 <80> 38 55 75 0e 80 78 01 aa 0f 84 a4 03 00 00 8d 74 26 00 68 dc 06 EAX: 3e8ed03c EBX: 00000000 ECX: 3e8ed03c EDX: 00010000 ESI: 00040000 EDI: eec04000 EBP: eef3fc60 ESP: eef3fbe0 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010206 CR0: 80050033 CR2: 3e8ed03c CR3: 2ec77000 CR4: 000006d0 Call Trace: r520_init+0x26/0x240 [radeon] radeon_device_init+0x533/0xa50 [radeon] radeon_driver_load_kms+0x80/0x220 [radeon] drm_dev_register+0xa7/0x180 [drm] radeon_pci_probe+0x10f/0x1a0 [radeon] pci_device_probe+0xd4/0x140
Fix the issue by updating all drivers which can access a platform provided ROM. Instead of calling the helper function pci_platform_rom() which uses phys_to_virt(), call ioremap() directly on the pdev->rom.
radeon_read_platform_bios() previously directly accessed an __iomem pointer. Avoid this by calling memcpy_fromio() instead of kmemdup().
pci_platform_rom() now has no remaining callers, so remove it.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 31 +++++++++++-------- .../drm/nouveau/nvkm/subdev/bios/shadowpci.c | 17 ++++++++-- drivers/gpu/drm/radeon/radeon_bios.c | 30 +++++++++++------- drivers/pci/rom.c | 17 ---------- include/linux/pci.h | 1 - 5 files changed, 52 insertions(+), 44 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +18 -13
@@ -192,30 +192,35 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)static bool amdgpu_read_platform_bios (struct amdgpu_device *adev) { -uint8_t __iomem *bios; -size_t size; +phys_addr_t rom = adev->pdev->rom; +size_t romlen = adev->pdev->romlen; +void __iomem *bios; adev->bios =NULL ; - bios =pci_platform_rom (adev->pdev, &size); -if (!bios) { +if (!rom || romlen ==0 )return false; - } - adev->bios =kzalloc (size,GFP_KERNEL ); -if (adev->bios ==NULL ) + adev->bios =kzalloc (romlen,GFP_KERNEL ); +if (!adev->bios)return false; -memcpy_fromio (adev->bios, bios, size); + bios =ioremap (rom, romlen); +if (!bios) + goto free_bios; -if (!check_atom_bios (adev->bios, size)) { -kfree (adev->bios); -return false; - } +memcpy_fromio (adev->bios, bios, romlen); +iounmap (bios); - adev->bios_size = size; +if (!check_atom_bios (adev->bios, romlen)) + goto free_bios; + + adev->bios_size = romlen;return true; +free_bios: +kfree (adev->bios); +return false; }#ifdef CONFIG_ACPI
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c +15 -2
@@ -101,9 +101,13 @@ platform_init(struct nvkm_bios *bios, const char *name)else return ERR_PTR (-ENODEV ); +if (!pdev->rom || pdev->romlen ==0 ) +return ERR_PTR (-ENODEV ); +if ((priv =kmalloc (sizeof (*priv),GFP_KERNEL ))) { + priv->size = pdev->romlen;if (ret = -ENODEV , - (priv->rom =pci_platform_rom (pdev, &priv->size))) + (priv->rom =ioremap (pdev->rom, pdev->romlen)))return priv;kfree (priv); }
@@ -111,11 +115,20 @@ platform_init(struct nvkm_bios *bios, const char *name)return ERR_PTR (ret); } +static void +platform_fini (void *data) +{ +struct priv *priv = data; + +iounmap (priv->rom); +kfree (priv); +} +const struct nvbios_source nvbios_platform = { .name ="PLATFORM" , .init = platform_init, - .fini = (void (*)(void *))kfree, + .fini = platform_fini, .read = pcirom_read, .rw = true, };
drivers/gpu/drm/radeon/radeon_bios.c +19 -11
@@ -108,25 +108,33 @@ static bool radeon_read_bios(struct radeon_device *rdev)static bool radeon_read_platform_bios (struct radeon_device *rdev) { -uint8_t __iomem *bios; -size_t size; +phys_addr_t rom = rdev->pdev->rom; +size_t romlen = rdev->pdev->romlen; +void __iomem *bios; rdev->bios =NULL ; - bios =pci_platform_rom (rdev->pdev, &size); -if (!bios) { +if (!rom || romlen ==0 )return false; - } -if (size ==0 || bios[0 ] !=0x55 || bios[1 ] !=0xaa ) { + rdev->bios =kzalloc (romlen,GFP_KERNEL ); +if (!rdev->bios)return false; - } - rdev->bios =kmemdup (bios, size,GFP_KERNEL ); -if (rdev->bios ==NULL ) { -return false; - } + + bios =ioremap (rom, romlen); +if (!bios) + goto free_bios; + +memcpy_fromio (rdev->bios, bios, romlen); +iounmap (bios); + +if (rdev->bios[0 ] !=0x55 || rdev->bios[1 ] !=0xaa ) + goto free_bios;return true; +free_bios: +kfree (rdev->bios); +return false; }#ifdef CONFIG_ACPI
drivers/pci/rom.c +0 -17
@@ -195,20 +195,3 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)pci_disable_rom (pdev); }EXPORT_SYMBOL (pci_unmap_rom); - -/** -* pci_platform_rom - provides a pointer to any ROM image provided by the -* platform -* @pdev: pointer to pci device struct -* @size: pointer to receive size of pci window over ROM -*/ -void __iomem *pci_platform_rom (struct pci_dev *pdev,size_t *size) -{ -if (pdev->rom && pdev->romlen) { - *size = pdev->romlen; -return phys_to_virt ((phys_addr_t )pdev->rom); - } - -return NULL ; -} -EXPORT_SYMBOL (pci_platform_rom);
include/linux/pci.h +0 -1
@@ -1216,7 +1216,6 @@ int pci_enable_rom(struct pci_dev *pdev);void pci_disable_rom (struct pci_dev *pdev);void __iomem __must_check *pci_map_rom (struct pci_dev *pdev,size_t *size);void pci_unmap_rom (struct pci_dev *pdev,void __iomem *rom); -void __iomem __must_check *pci_platform_rom (struct pci_dev *pdev,size_t *size);/* Power management related routines */ int pci_save_state (struct pci_dev *dev);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 211/388 ubifs: ubifs_jnl_write_inode: Fix a memory leak bug
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
[ Upstream commit 81423c78551654953d746250f1721300b470be0e ]
When inodes with extended attributes are evicted, xent is not freed in one exit branch.
--- fs/ubifs/journal.c | 1 + 1 file changed, 1 insertion(+)
fs/ubifs/journal.c +1 -0
@@ -906,6 +906,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)ubifs_err (c,"dead directory entry '%s', error %d" , xent->name, err);ubifs_ro_mode (c, err); +kfree (xent); goto out_release; }ubifs_assert (c,ubifs_inode (xino)->xattr);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 212/388 ubifs: ubifs_add_orphan: Fix a memory leak bug
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
[ Upstream commit 927cc5cec35f01fe4f8af0ba80830a90b0533983 ]
Memory leak occurs when files with extended attributes are added to orphan list.
--- fs/ubifs/orphan.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
fs/ubifs/orphan.c +7 -2
@@ -157,7 +157,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)int err =0 ;ino_t xattr_inum;union ubifs_key key; -struct ubifs_dent_node *xent; +struct ubifs_dent_node *xent, *pxent =NULL ;struct fscrypt_name nm = {0 };struct ubifs_orphan *xattr_orphan;struct ubifs_orphan *orphan;
@@ -181,11 +181,16 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) xattr_inum =le64_to_cpu (xent->inum); xattr_orphan =orphan_add (c, xattr_inum, orphan); -if (IS_ERR (xattr_orphan)) +if (IS_ERR (xattr_orphan)) { +kfree (xent);return PTR_ERR (xattr_orphan); + } +kfree (pxent); + pxent = xent;key_read (c, &xent->key, &key); } +kfree (pxent);return 0 ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 213/388 ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
In reply to Greg Kroah-HartmanFrom: Liu Song <[email protected]>
[ Upstream commit acc5af3efa303d5f36cc8c0f61716161f6ca1384 ]
In “ubifs_check_node”, when the value of "node_len" is abnormal, the code will goto label of "out_len" for execution. Then, in the following "ubifs_dump_node", if inode type is "UBIFS_DATA_NODE", in "print_hex_dump", an out-of-bounds access may occur due to the wrong "ch->len".
Therefore, when the value of "node_len" is abnormal, data length should to be adjusted to a reasonable safe range. At this time, structured data is not credible, so dump the corrupted data directly for analysis.
--- fs/ubifs/io.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
fs/ubifs/io.c +14 -2
@@ -225,7 +225,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)int ubifs_check_node (const struct ubifs_info *c,const void *buf,int lnum,int offs,int quiet,int must_chk_crc) { -int err = -EINVAL , type, node_len; +int err = -EINVAL , type, node_len, dump_node =1 ;uint32_t crc, node_crc, magic;const struct ubifs_ch *ch = buf;
@@ -278,10 +278,22 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, out_len:if (!quiet)ubifs_err (c,"bad node length %d" , node_len); +if (type ==UBIFS_DATA_NODE && node_len >UBIFS_DATA_NODE_SZ ) + dump_node =0 ; out:if (!quiet) {ubifs_err (c,"bad node at LEB %d:%d" , lnum, offs); -ubifs_dump_node (c, buf); +if (dump_node) { +ubifs_dump_node (c, buf); + }else { +int safe_len =min3 (node_len, c->leb_size - offs, + (int )UBIFS_MAX_DATA_NODE_SZ ); +pr_err ("\tprevent out-of-bounds memory access\n" ); +pr_err ("\ttruncated data node length %d\n" , safe_len); +pr_err ("\tcorrupted data node:\n" ); +print_hex_dump (KERN_ERR ,"\t" ,DUMP_PREFIX_OFFSET ,32 ,1 , + buf, safe_len,0 ); + }dump_stack (); }return err;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 214/388 ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra endpoint descriptor
In reply to Greg Kroah-HartmanFrom: Andreas Steinmetz <[email protected]>
[ Upstream commit 5c6cd7021a05a02fcf37f360592d7c18d4d807fb ]
The Miditech MIDIFACE 16x16 (USB ID 1290:1749) has more than one extra endpoint descriptor.
The first extra descriptor is: 0x06 0x30 0x00 0x00 0x00 0x00
As the code in snd_usbmidi_get_ms_info() looks only at the first extra descriptor to find USB_DT_CS_ENDPOINT the device as such is recognized but there is neither input nor output configured.
The patch iterates through the extra descriptors to find the proper one. With this patch the device is correctly configured.
--- sound/usb/midi.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
sound/usb/midi.c +24 -5
@@ -1827,6 +1827,28 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi,return 0 ; } +static struct usb_ms_endpoint_descriptor *find_usb_ms_endpoint_descriptor ( +struct usb_host_endpoint *hostep) +{ +unsigned char *extra = hostep->extra; +int extralen = hostep->extralen; + +while (extralen >3 ) { +struct usb_ms_endpoint_descriptor *ms_ep = + (struct usb_ms_endpoint_descriptor *)extra; + +if (ms_ep->bLength >3 && + ms_ep->bDescriptorType ==USB_DT_CS_ENDPOINT && + ms_ep->bDescriptorSubtype ==UAC_MS_GENERAL ) +return ms_ep; +if (!extra[0 ]) +break ; + extralen -= extra[0 ]; + extra += extra[0 ]; + } +return NULL ; +} +/* * Returns MIDIStreaming device capabilities. */
@@ -1864,11 +1886,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, ep =get_ep_desc (hostep);if (!usb_endpoint_xfer_bulk (ep) && !usb_endpoint_xfer_int (ep))continue ; - ms_ep = (struct usb_ms_endpoint_descriptor *)hostep->extra; -if (hostep->extralen <4 || - ms_ep->bLength <4 || - ms_ep->bDescriptorType !=USB_DT_CS_ENDPOINT || - ms_ep->bDescriptorSubtype !=UAC_MS_GENERAL ) + ms_ep =find_usb_ms_endpoint_descriptor (hostep); +if (!ms_ep)continue ;if (usb_endpoint_dir_out (ep)) {if (endpoints[epidx].out_ep) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 215/388 PCI: pciehp: Fix MSI interrupt race
In reply to Greg Kroah-HartmanFrom: Stuart Hayes <[email protected]>
[ Upstream commit 8edf5332c39340b9583cf9cba659eb7ec71f75b5 ]
Without this commit, a PCIe hotplug port can stop generating interrupts on hotplug events, so device adds and removals will not be seen:
The pciehp interrupt handler pciehp_isr() reads the Slot Status register and then writes back to it to clear the bits that caused the interrupt. If a different interrupt event bit gets set between the read and the write, pciehp_isr() returns without having cleared all of the interrupt event bits. If this happens when the MSI isn't masked (which by default it isn't in handle_edge_irq(), and which it will never be when MSI per-vector masking is not supported), we won't get any more hotplug interrupts from that device.
That is expected behavior, according to the PCIe Base Spec r5.0, section 6.7.3.4, "Software Notification of Hot-Plug Events".
Because the Presence Detect Changed and Data Link Layer State Changed event bits can both get set at nearly the same time when a device is added or removed, this is more likely to happen than it might seem. The issue was found (and can be reproduced rather easily) by connecting and disconnecting an NVMe storage device on at least one system model where the NVMe devices were being connected to an AMD PCIe port (PCI device 0x1022/0x1483).
Fix the issue by modifying pciehp_isr() to loop back and re-read the Slot Status register immediately after writing to it, until it sees that all of the event status bits have been cleared.
[lukas: drop loop count limitation, write "events" instead of "status", don't loop back in INTx and poll modes, tweak code comment & commit msg]
--- drivers/pci/hotplug/pciehp_hpc.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
drivers/pci/hotplug/pciehp_hpc.c +20 -6
@@ -529,7 +529,7 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)struct controller *ctrl = (struct controller *)dev_id;struct pci_dev *pdev =ctrl_dev (ctrl);struct device *parent = pdev->dev.parent; -u16 status, events; +u16 status, events =0 ;/* * Interrupts only occur in D3hot or shallower and only if enabled
@@ -554,6 +554,7 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id) } } +read_status:pcie_capability_read_word (pdev,PCI_EXP_SLTSTA , &status);if (status == (u16 ) ~0 ) {ctrl_info (ctrl,"%s: no response from device\n" , __func__);
@@ -566,24 +567,37 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)* Slot Status contains plain status bits as well as event * notification bits; right now we only want the event bits. */ - events = status & (PCI_EXP_SLTSTA_ABP |PCI_EXP_SLTSTA_PFD | -PCI_EXP_SLTSTA_PDC |PCI_EXP_SLTSTA_CC | -PCI_EXP_SLTSTA_DLLSC ); + status &=PCI_EXP_SLTSTA_ABP |PCI_EXP_SLTSTA_PFD | +PCI_EXP_SLTSTA_PDC |PCI_EXP_SLTSTA_CC | +PCI_EXP_SLTSTA_DLLSC ;/* * If we've already reported a power fault, don't report it again * until we've done something to handle it. */ if (ctrl->power_fault_detected) - events &= ~PCI_EXP_SLTSTA_PFD ; + status &= ~PCI_EXP_SLTSTA_PFD ; + events |= status;if (!events) {if (parent)pm_runtime_put (parent);return IRQ_NONE ; } -pcie_capability_write_word (pdev,PCI_EXP_SLTSTA , events); +if (status) { +pcie_capability_write_word (pdev,PCI_EXP_SLTSTA , events); + +/* +* In MSI mode, all event bits must be zero before the port +* will send a new interrupt (PCIe Base Spec r5.0 sec 6.7.3.4). +* So re-read the Slot Status register in case a bit was set +* between read and write. +*/ +if (pci_dev_msi_enabled (pdev) && !pciehp_poll_mode) + goto read_status; + } +ctrl_dbg (ctrl,"pending interrupts %#06x from Slot Status\n" , events);if (parent)pm_runtime_put (parent);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 216/388 NFS: Fix races nfs_page_group_destroy() vs nfs_destroy_unlinked_subrequests()
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
[ Upstream commit 08ca8b21f760c0ed5034a5c122092eec22ccf8f4 ]
When a subrequest is being detached from the subgroup, we want to ensure that it is not holding the group lock, or in the process of waiting for the group lock.
--- fs/nfs/pagelist.c | 67 +++++++++++++++++++++++++++------------- fs/nfs/write.c | 10 ++++-- include/linux/nfs_page.h | 2 ++ 3 files changed, 55 insertions(+), 24 deletions(-)
fs/nfs/pagelist.c +45 -22
@@ -133,47 +133,70 @@ nfs_async_iocounter_wait(struct rpc_task *task, struct nfs_lock_context *l_ctx)EXPORT_SYMBOL_GPL (nfs_async_iocounter_wait);/* -* nfs_page_group_lock - lock the head of the page group -* @req - request in group that is to be locked +* nfs_page_set_headlock - set the request PG_HEADLOCK +* @req: request that is to be locked * -* this lock must be held when traversing or modifying the page -* group list +* this lock must be held when modifying req->wb_head * * return 0 on success, < 0 on error */ int -nfs_page_group_lock (struct nfs_page *req) +nfs_page_set_headlock (struct nfs_page *req) { -struct nfs_page *head = req->wb_head; - -WARN_ON_ONCE (head != head->wb_head); - -if (!test_and_set_bit (PG_HEADLOCK , &head->wb_flags)) +if (!test_and_set_bit (PG_HEADLOCK , &req->wb_flags))return 0 ; -set_bit (PG_CONTENDED1 , &head->wb_flags); +set_bit (PG_CONTENDED1 , &req->wb_flags);smp_mb__after_atomic (); -return wait_on_bit_lock (&head->wb_flags,PG_HEADLOCK , +return wait_on_bit_lock (&req->wb_flags,PG_HEADLOCK ,TASK_UNINTERRUPTIBLE ); }/* -* nfs_page_group_unlock - unlock the head of the page group -* @req - request in group that is to be unlocked +* nfs_page_clear_headlock - clear the request PG_HEADLOCK +* @req: request that is to be locked */ void -nfs_page_group_unlock (struct nfs_page *req) +nfs_page_clear_headlock (struct nfs_page *req) { -struct nfs_page *head = req->wb_head; - -WARN_ON_ONCE (head != head->wb_head); -smp_mb__before_atomic (); -clear_bit (PG_HEADLOCK , &head->wb_flags); +clear_bit (PG_HEADLOCK , &req->wb_flags);smp_mb__after_atomic (); -if (!test_bit (PG_CONTENDED1 , &head->wb_flags)) +if (!test_bit (PG_CONTENDED1 , &req->wb_flags))return ; -wake_up_bit (&head->wb_flags,PG_HEADLOCK ); +wake_up_bit (&req->wb_flags,PG_HEADLOCK ); +} + +/* +* nfs_page_group_lock - lock the head of the page group +* @req: request in group that is to be locked +* +* this lock must be held when traversing or modifying the page +* group list +* +* return 0 on success, < 0 on error +*/ +int +nfs_page_group_lock (struct nfs_page *req) +{ +int ret; + + ret =nfs_page_set_headlock (req); +if (ret || req->wb_head == req) +return ret; +return nfs_page_set_headlock (req->wb_head); +} + +/* +* nfs_page_group_unlock - unlock the head of the page group +* @req: request in group that is to be unlocked +*/ +void +nfs_page_group_unlock (struct nfs_page *req) +{ +if (req != req->wb_head) +nfs_page_clear_headlock (req->wb_head); +nfs_page_clear_headlock (req); }/*
fs/nfs/write.c +8 -2
@@ -425,22 +425,28 @@ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list, destroy_list = (subreq->wb_this_page == old_head) ?NULL : subreq->wb_this_page; +/* Note: lock subreq in order to change subreq->wb_head */ +nfs_page_set_headlock (subreq);WARN_ON_ONCE (old_head != subreq->wb_head);/* make sure old group is not used */ subreq->wb_this_page = subreq; + subreq->wb_head = subreq;clear_bit (PG_REMOVE , &subreq->wb_flags);/* Note: races with nfs_page_group_destroy() */ if (!kref_read (&subreq->wb_kref)) {/* Check if we raced with nfs_page_group_destroy() */ -if (test_and_clear_bit (PG_TEARDOWN , &subreq->wb_flags)) +if (test_and_clear_bit (PG_TEARDOWN , &subreq->wb_flags)) { +nfs_page_clear_headlock (subreq);nfs_free_request (subreq); + }else +nfs_page_clear_headlock (subreq);continue ; } +nfs_page_clear_headlock (subreq); - subreq->wb_head = subreq;nfs_release_request (old_head);if (test_and_clear_bit (PG_INODE_REF , &subreq->wb_flags)) {
include/linux/nfs_page.h +2 -0
@@ -142,6 +142,8 @@ extern void nfs_unlock_and_release_request(struct nfs_page *);extern int nfs_page_group_lock (struct nfs_page *);extern void nfs_page_group_unlock (struct nfs_page *);extern bool nfs_page_group_sync_on_bit (struct nfs_page *,unsigned int ); +extern int nfs_page_set_headlock (struct nfs_page *req); +extern void nfs_page_clear_headlock (struct nfs_page *req);extern bool nfs_async_iocounter_wait (struct rpc_task *,struct nfs_lock_context *);/*
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 217/388 drm/amdgpu/vcn2.0: stall DPG when WPTR/RPTR reset
In reply to Greg Kroah-HartmanFrom: James Zhu <[email protected]>
[ Upstream commit ef563ff403404ef2f234abe79bdd9f04ab6481c9 ]
Add vcn dpg harware synchronization to fix race condition issue between vcn driver and hardware.
--- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +16 -0
@@ -1026,6 +1026,10 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect) tmp =REG_SET_FIELD (tmp,UVD_RBC_RB_CNTL ,RB_RPTR_WR_EN ,1 );WREG32_SOC15 (UVD ,0 , mmUVD_RBC_RB_CNTL, tmp); +/* Stall DPG before WPTR/RPTR reset */ +WREG32_P (SOC15_REG_OFFSET (UVD ,0 , mmUVD_POWER_STATUS), +UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK , + ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK );/* set the write pointer delay */ WREG32_SOC15 (UVD ,0 , mmUVD_RBC_RB_WPTR_CNTL,0 );
@@ -1048,6 +1052,9 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)WREG32_SOC15 (UVD ,0 , mmUVD_RBC_RB_WPTR,lower_32_bits (ring->wptr)); +/* Unstall DPG */ +WREG32_P (SOC15_REG_OFFSET (UVD ,0 , mmUVD_POWER_STATUS), +0 , ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK );return 0 ; }
@@ -1357,8 +1364,13 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK , UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, ret_code); +/* Stall DPG before WPTR/RPTR reset */ +WREG32_P (SOC15_REG_OFFSET (UVD ,0 , mmUVD_POWER_STATUS), +UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK , + ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK );/* Restore */ ring = &adev->vcn.inst->ring_enc[0 ]; + ring->wptr =0 ;WREG32_SOC15 (UVD ,0 , mmUVD_RB_BASE_LO, ring->gpu_addr);WREG32_SOC15 (UVD ,0 , mmUVD_RB_BASE_HI,upper_32_bits (ring->gpu_addr));WREG32_SOC15 (UVD ,0 , mmUVD_RB_SIZE, ring->ring_size /4 );
@@ -1366,6 +1378,7 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,WREG32_SOC15 (UVD ,0 , mmUVD_RB_WPTR,lower_32_bits (ring->wptr)); ring = &adev->vcn.inst->ring_enc[1 ]; + ring->wptr =0 ;WREG32_SOC15 (UVD ,0 , mmUVD_RB_BASE_LO2, ring->gpu_addr);WREG32_SOC15 (UVD ,0 , mmUVD_RB_BASE_HI2,upper_32_bits (ring->gpu_addr));WREG32_SOC15 (UVD ,0 , mmUVD_RB_SIZE2, ring->ring_size /4 );
@@ -1374,6 +1387,9 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,WREG32_SOC15 (UVD ,0 , mmUVD_RBC_RB_WPTR,RREG32_SOC15 (UVD ,0 , mmUVD_SCRATCH2) &0x7FFFFFFF ); +/* Unstall DPG */ +WREG32_P (SOC15_REG_OFFSET (UVD ,0 , mmUVD_POWER_STATUS), +0 , ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK ); SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS, UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 218/388 powerpc/perf: Implement a global lock to avoid races between trace, core and thread imc events.
In reply to Greg Kroah-HartmanFrom: Anju T Sudhakar <[email protected]>
[ Upstream commit a36e8ba60b991d563677227f172db69e030797e6 ]
IMC(In-memory Collection Counters) does performance monitoring in two different modes, i.e accumulation mode(core-imc and thread-imc events), and trace mode(trace-imc events). A cpu thread can either be in accumulation-mode or trace-mode at a time and this is done via the LDBAR register in POWER architecture. The current design does not address the races between thread-imc and trace-imc events.
Patch implements a global id and lock to avoid the races between core, trace and thread imc events. With this global id-lock implementation, the system can either run core, thread or trace imc events at a time. i.e. to run any core-imc events, thread/trace imc events should not be enabled/monitored.
--- arch/powerpc/perf/imc-pmu.c | 173 +++++++++++++++++++++++++++++++----- 1 file changed, 149 insertions(+), 24 deletions(-)
arch/powerpc/perf/imc-pmu.c +149 -24
@@ -44,6 +44,16 @@ static DEFINE_PER_CPU(u64 *, trace_imc_mem);static struct imc_pmu_ref *trace_imc_refc;static int trace_imc_mem_size; +/* +* Global data structure used to avoid races between thread, +* core and trace-imc +*/ +static struct imc_pmu_ref imc_global_refc = { + .lock =__MUTEX_INITIALIZER (imc_global_refc.lock), + .id =0 , + .refc =0 , +}; +static struct imc_pmu *imc_event_to_pmu (struct perf_event *event) { return container_of(event->pmu, struct imc_pmu, pmu);
@@ -698,6 +708,16 @@ static int ppc_core_imc_cpu_offline(unsigned int cpu)return -EINVAL ; ref->refc =0 ; +/* +* Reduce the global reference count, if this is the +* last cpu in this core and core-imc event running +* in this cpu. +*/ +mutex_lock (&imc_global_refc.lock); +if (imc_global_refc.id ==IMC_DOMAIN_CORE ) + imc_global_refc.refc--; + +mutex_unlock (&imc_global_refc.lock); }return 0 ; }
@@ -710,6 +730,23 @@ static int core_imc_pmu_cpumask_init(void) ppc_core_imc_cpu_offline); } +static void reset_global_refc (struct perf_event *event) +{ +mutex_lock (&imc_global_refc.lock); + imc_global_refc.refc--; + +/* +* If no other thread is running any +* event for this domain(thread/core/trace), +* set the global id to zero. +*/ +if (imc_global_refc.refc <=0 ) { + imc_global_refc.refc =0 ; + imc_global_refc.id =0 ; + } +mutex_unlock (&imc_global_refc.lock); +} +static void core_imc_counters_release (struct perf_event *event) {int rc, core_id;
@@ -759,6 +796,8 @@ static void core_imc_counters_release(struct perf_event *event) ref->refc =0 ; }mutex_unlock (&ref->lock); + +reset_global_refc (event); }static int core_imc_event_init (struct perf_event *event)
@@ -819,6 +858,29 @@ static int core_imc_event_init(struct perf_event *event) ++ref->refc;mutex_unlock (&ref->lock); +/* +* Since the system can run either in accumulation or trace-mode +* of IMC at a time, core-imc events are allowed only if no other +* trace/thread imc events are enabled/monitored. +* +* Take the global lock, and check the refc.id +* to know whether any other trace/thread imc +* events are running. +*/ +mutex_lock (&imc_global_refc.lock); +if (imc_global_refc.id ==0 || imc_global_refc.id ==IMC_DOMAIN_CORE ) { +/* +* No other trace/thread imc events are running in +* the system, so set the refc.id to core-imc. +*/ + imc_global_refc.id =IMC_DOMAIN_CORE ; + imc_global_refc.refc++; + }else { +mutex_unlock (&imc_global_refc.lock); +return -EBUSY ; + } +mutex_unlock (&imc_global_refc.lock); + event->hw.event_base = (u64 )pcmi->vbase + (config &IMC_EVENT_OFFSET_MASK ); event->destroy = core_imc_counters_release;return 0 ;
@@ -877,7 +939,23 @@ static int ppc_thread_imc_cpu_online(unsigned int cpu)static int ppc_thread_imc_cpu_offline (unsigned int cpu) { -mtspr (SPRN_LDBAR ,0 ); +/* +* Set the bit 0 of LDBAR to zero. +* +* If bit 0 of LDBAR is unset, it will stop posting +* the counter data to memory. +* For thread-imc, bit 0 of LDBAR will be set to 1 in the +* event_add function. So reset this bit here, to stop the updates +* to memory in the cpu_offline path. +*/ +mtspr (SPRN_LDBAR , (mfspr (SPRN_LDBAR ) & (~(1UL <<63 )))); + +/* Reduce the refc if thread-imc event running on this cpu */ +mutex_lock (&imc_global_refc.lock); +if (imc_global_refc.id ==IMC_DOMAIN_THREAD ) + imc_global_refc.refc--; +mutex_unlock (&imc_global_refc.lock); +return 0 ; }
@@ -916,7 +994,22 @@ static int thread_imc_event_init(struct perf_event *event)if (!target)return -EINVAL ; +mutex_lock (&imc_global_refc.lock); +/* +* Check if any other trace/core imc events are running in the +* system, if not set the global id to thread-imc. +*/ +if (imc_global_refc.id ==0 || imc_global_refc.id ==IMC_DOMAIN_THREAD ) { + imc_global_refc.id =IMC_DOMAIN_THREAD ; + imc_global_refc.refc++; + }else { +mutex_unlock (&imc_global_refc.lock); +return -EBUSY ; + } +mutex_unlock (&imc_global_refc.lock); + event->pmu->task_ctx_nr = perf_sw_context; + event->destroy = reset_global_refc;return 0 ; }
@@ -1063,10 +1156,12 @@ static void thread_imc_event_del(struct perf_event *event, int flags)int core_id;struct imc_pmu_ref *ref; -mtspr (SPRN_LDBAR ,0 ); - core_id =smp_processor_id () / threads_per_core; ref = &core_imc_refc[core_id]; +if (!ref) { +pr_debug ("imc: Failed to get event reference count\n" ); +return ; + }mutex_lock (&ref->lock); ref->refc--;
@@ -1082,6 +1177,10 @@ static void thread_imc_event_del(struct perf_event *event, int flags) ref->refc =0 ; }mutex_unlock (&ref->lock); + +/* Set bit 0 of LDBAR to zero, to stop posting updates to memory */ +mtspr (SPRN_LDBAR , (mfspr (SPRN_LDBAR ) & (~(1UL <<63 )))); +/* * Take a snapshot and calculate the delta and update * the event counter values.
@@ -1133,7 +1232,18 @@ static int ppc_trace_imc_cpu_online(unsigned int cpu)static int ppc_trace_imc_cpu_offline (unsigned int cpu) { -mtspr (SPRN_LDBAR ,0 ); +/* +* No need to set bit 0 of LDBAR to zero, as +* it is set to zero for imc trace-mode +* +* Reduce the refc if any trace-imc event running +* on this cpu. +*/ +mutex_lock (&imc_global_refc.lock); +if (imc_global_refc.id ==IMC_DOMAIN_TRACE ) + imc_global_refc.refc--; +mutex_unlock (&imc_global_refc.lock); +return 0 ; }
@@ -1226,15 +1336,14 @@ static int trace_imc_event_add(struct perf_event *event, int flags) local_mem =get_trace_imc_event_base_addr (); ldbar_value = ((u64 )local_mem &THREAD_IMC_LDBAR_MASK ) |TRACE_IMC_ENABLE ; -if (core_imc_refc) - ref = &core_imc_refc[core_id]; +/* trace-imc reference count */ +if (trace_imc_refc) + ref = &trace_imc_refc[core_id];if (!ref) { -/* If core-imc is not enabled, use trace-imc reference count */ -if (trace_imc_refc) - ref = &trace_imc_refc[core_id]; -if (!ref) -return -EINVAL ; +pr_debug ("imc: Failed to get the event reference count\n" ); +return -EINVAL ; } +mtspr (SPRN_LDBAR , ldbar_value);mutex_lock (&ref->lock);if (ref->refc ==0 ) {
@@ -1242,13 +1351,11 @@ static int trace_imc_event_add(struct perf_event *event, int flags) get_hard_smp_processor_id(smp_processor_id()))) {mutex_unlock (&ref->lock);pr_err ("trace-imc: Unable to start the counters for core %d\n" , core_id); -mtspr (SPRN_LDBAR ,0 );return -EINVAL ; } } ++ref->refc;mutex_unlock (&ref->lock); -return 0 ; }
@@ -1274,16 +1381,13 @@ static void trace_imc_event_del(struct perf_event *event, int flags)int core_id =smp_processor_id () / threads_per_core;struct imc_pmu_ref *ref =NULL ; -if (core_imc_refc) - ref = &core_imc_refc[core_id]; +if (trace_imc_refc) + ref = &trace_imc_refc[core_id];if (!ref) { -/* If core-imc is not enabled, use trace-imc reference count */ -if (trace_imc_refc) - ref = &trace_imc_refc[core_id]; -if (!ref) -return ; +pr_debug ("imc: Failed to get event reference count\n" ); +return ; } -mtspr (SPRN_LDBAR ,0 ); +mutex_lock (&ref->lock); ref->refc--;if (ref->refc ==0 ) {
@@ -1297,6 +1401,7 @@ static void trace_imc_event_del(struct perf_event *event, int flags) ref->refc =0 ; }mutex_unlock (&ref->lock); +trace_imc_event_stop (event, flags); }
@@ -1314,10 +1419,30 @@ static int trace_imc_event_init(struct perf_event *event)if (event->attr.sample_period ==0 )return -ENOENT ; +/* +* Take the global lock, and make sure +* no other thread is running any core/thread imc +* events +*/ +mutex_lock (&imc_global_refc.lock); +if (imc_global_refc.id ==0 || imc_global_refc.id ==IMC_DOMAIN_TRACE ) { +/* +* No core/thread imc events are running in the +* system, so set the refc.id to trace-imc. +*/ + imc_global_refc.id =IMC_DOMAIN_TRACE ; + imc_global_refc.refc++; + }else { +mutex_unlock (&imc_global_refc.lock); +return -EBUSY ; + } +mutex_unlock (&imc_global_refc.lock); + event->hw.idx =-1 ; target = event->hw.target; event->pmu->task_ctx_nr = perf_hw_context; + event->destroy = reset_global_refc;return 0 ; }
@@ -1429,10 +1554,10 @@ static void cleanup_all_core_imc_memory(void)static void thread_imc_ldbar_disable (void *dummy) {/* -* By Zeroing LDBAR, we disable thread-imc -* updates. +* By setting 0th bit of LDBAR to zero, we disable thread-imc +* updates to memory. */ -mtspr (SPRN_LDBAR ,0 ); +mtspr (SPRN_LDBAR , (mfspr (SPRN_LDBAR ) & (~(1UL <<63 )))); }void thread_imc_disable (void )
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 219/388 mm/kmemleak.c: use address-of operator on section symbols
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit b0d14fc43d39203ae025f20ef4d5d25d9ccf4be1 ]
Clang warns:
mm/kmemleak.c:1955:28: warning: array comparison always evaluates to a constant [-Wtautological-compare]
if (__start_ro_after_init < _sdata || __end_ro_after_init > _edata)
^
mm/kmemleak.c:1955:60: warning: array comparison always evaluates to a constant [-Wtautological-compare]
if (__start_ro_after_init < _sdata || __end_ro_after_init > _edata)These are not true arrays, they are linker defined symbols, which are just addresses. Using the address of operator silences the warning and does not change the resulting assembly with either clang/ld.lld or gcc/ld (tested with diff + objdump -Dr).
--- mm/kmemleak.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/kmemleak.c +1 -1
@@ -1947,7 +1947,7 @@ void __init kmemleak_init(void)create_object ((unsigned long )__bss_start, __bss_stop - __bss_start,KMEMLEAK_GREY ,GFP_ATOMIC );/* only register .data..ro_after_init if not within .data */ -if (__start_ro_after_init < _sdata || __end_ro_after_init > _edata) +if (&__start_ro_after_init < &_sdata || &__end_ro_after_init > &_edata)create_object ((unsigned long )__start_ro_after_init, __end_ro_after_init - __start_ro_after_init,KMEMLEAK_GREY ,GFP_ATOMIC );
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 220/388 mm/filemap.c: clear page error before actual read
In reply to Greg Kroah-HartmanFrom: Xianting Tian <[email protected]>
[ Upstream commit faffdfa04fa11ccf048cebdde73db41ede0679e0 ]
Mount failure issue happens under the scenario: Application forked dozens of threads to mount the same number of cramfs images separately in docker, but several mounts failed with high probability. Mount failed due to the checking result of the page(read from the superblock of loop dev) is not uptodate after wait_on_page_locked(page) returned in function cramfs_read:
wait_on_page_locked(page);
if (!PageUptodate(page)) {
...
}The reason of the checking result of the page not uptodate: systemd-udevd read the loopX dev before mount, because the status of loopX is Lo_unbound at this time, so loop_make_request directly trigger the calling of io_end handler end_buffer_async_read, which called SetPageError(page). So It caused the page can't be set to uptodate in function end_buffer_async_read:
if(page_uptodate && !PageError(page)) {
SetPageUptodate(page);
}Then mount operation is performed, it used the same page which is just accessed by systemd-udevd above, Because this page is not uptodate, it will launch a actual read via submit_bh, then wait on this page by calling wait_on_page_locked(page). When the I/O of the page done, io_end handler end_buffer_async_read is called, because no one cleared the page error(during the whole read path of mount), which is caused by systemd-udevd reading, so this page is still in "PageError" status, which can't be set to uptodate in function end_buffer_async_read, then caused mount failure.
But sometimes mount succeed even through systemd-udeved read loopX dev just before, The reason is systemd-udevd launched other loopX read just between step 3.1 and 3.2, the steps as below:
1, loopX dev default status is Lo_unbound;
2, systemd-udved read loopX dev (page is set to PageError); 3, mount operation
1) set loopX status to Lo_bound; ==>systemd-udevd read loopX dev<==
2) read loopX dev(page has no error)
3) mount succeed
As the loopX dev status is set to Lo_bound after step 3.1, so the other loopX dev read by systemd-udevd will go through the whole I/O stack, part of the call trace as below:
SYS_read
vfs_read
do_sync_read
blkdev_aio_read
generic_file_aio_read
do_generic_file_read:
ClearPageError(page);
mapping->a_ops->readpage(filp, page);here, mapping->a_ops->readpage() is blkdev_readpage. In latest kernel, some function name changed, the call trace as below:
blkdev_read_iter
generic_file_read_iter
generic_file_buffered_read:
/*
* A previous I/O error may have been due to temporary
* failures, eg. mutipath errors.
* Pg_error will be set again if readpage fails.
*/
ClearPageError(page);
/* Start the actual read. The read will unlock the page*/
error=mapping->a_ops->readpage(flip, page);We can see ClearPageError(page) is called before the actual read, then the read in step 3.2 succeed.
This patch is to add the calling of ClearPageError just before the actual read of read path of cramfs mount. Without the patch, the call trace as below when performing cramfs mount:
do_mount
cramfs_read
cramfs_blkdev_read
read_cache_page
do_read_cache_page:
filler(data, page);
or
mapping->a_ops->readpage(data, page);With the patch, the call trace as below when performing mount:
do_mount
cramfs_read
cramfs_blkdev_read
read_cache_page:
do_read_cache_page:
ClearPageError(page); <== new add
filler(data, page);
or
mapping->a_ops->readpage(data, page);With the patch, mount operation trigger the calling of ClearPageError(page) before the actual read, the page has no error if no additional page error happen when I/O done.
--- mm/filemap.c | 8 ++++++++ 1 file changed, 8 insertions(+)
mm/filemap.c +8 -0
@@ -2845,6 +2845,14 @@ filler:unlock_page (page); goto out; } + +/* +* A previous I/O error may have been due to temporary +* failures. +* Clear page error before actual read, PG_error will be +* set again if read page fails. +*/ +ClearPageError (page); goto filler; out:
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 221/388 mm/swapfile: fix data races in try_to_unuse()
In reply to Greg Kroah-HartmanFrom: Qian Cai <[email protected]>
[ Upstream commit 218209487c3da2f6d861b236c11226b6eca7b7b7 ]
si->inuse_pages could be accessed concurrently as noticed by KCSAN,
write to 0xffff98b00ebd04dc of 4 bytes by task 82262 on cpu 92:
swap_range_free+0xbe/0x230 swap_range_free at mm/swapfile.c:719 swapcache_free_entries+0x1be/0x250 free_swap_slot+0x1c8/0x220 __swap_entry_free.constprop.19+0xa3/0xb0 free_swap_and_cache+0x53/0xa0 unmap_page_range+0x7e0/0x1ce0 unmap_single_vma+0xcd/0x170 unmap_vmas+0x18b/0x220 exit_mmap+0xee/0x220 mmput+0xe7/0x240 do_exit+0x598/0xfd0 do_group_exit+0x8b/0x180 get_signal+0x293/0x13d0 do_signal+0x37/0x5d0 prepare_exit_to_usermode+0x1b7/0x2c0 ret_from_intr+0x32/0x42
read to 0xffff98b00ebd04dc of 4 bytes by task 82499 on cpu 46:
try_to_unuse+0x86b/0xc80 try_to_unuse at mm/swapfile.c:2185 __x64_sys_swapoff+0x372/0xd40 do_syscall_64+0x91/0xb05 entry_SYSCALL_64_after_hwframe+0x49/0xbe
The plain reads in try_to_unuse() are outside si->lock critical section which result in data races that could be dangerous to be used in a loop. Fix them by adding READ_ONCE().
--- mm/swapfile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
mm/swapfile.c +4 -4
@@ -2132,7 +2132,7 @@ int try_to_unuse(unsigned int type, bool frontswap,swp_entry_t entry;unsigned int i; -if (!si->inuse_pages) +if (!READ_ONCE (si->inuse_pages))return 0 ;if (!frontswap)
@@ -2148,7 +2148,7 @@ retry:spin_lock (&mmlist_lock); p = &init_mm.mmlist; -while (si->inuse_pages && +while (READ_ONCE (si->inuse_pages) && !signal_pending (current) && (p = p->next) != &init_mm.mmlist) {
@@ -2177,7 +2177,7 @@ retry:mmput (prev_mm); i =0 ; -while (si->inuse_pages && +while (READ_ONCE (si->inuse_pages) && !signal_pending (current) && (i =find_next_to_unuse (si, i, frontswap)) !=0 ) {
@@ -2219,7 +2219,7 @@ retry:* been preempted after get_swap_page(), temporarily hiding that swap. * It's easy and robust (though cpu-intensive) just to keep retrying. */ -if (si->inuse_pages) { +if (READ_ONCE (si->inuse_pages)) {if (!signal_pending (current)) goto retry; retval = -EINTR ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 222/388 mm/vmscan.c: fix data races using kswapd_classzone_idx
In reply to Greg Kroah-HartmanFrom: Qian Cai <[email protected]>
[ Upstream commit 5644e1fbbfe15ad06785502bbfe5751223e5841d ]
pgdat->kswapd_classzone_idx could be accessed concurrently in wakeup_kswapd(). Plain writes and reads without any lock protection result in data races. Fix them by adding a pair of READ|WRITE_ONCE() as well as saving a branch (compilers might well optimize the original code in an unintentional way anyway). While at it, also take care of pgdat->kswapd_order and non-kswapd threads in allow_direct_reclaim(). The data races were reported by KCSAN,
BUG: KCSAN: data-race in wakeup_kswapd / wakeup_kswapd
write to 0xffff9f427ffff2dc of 4 bytes by task 7454 on cpu 13:
wakeup_kswapd+0xf1/0x400 wakeup_kswapd at mm/vmscan.c:3967 wake_all_kswapds+0x59/0xc0 wake_all_kswapds at mm/page_alloc.c:4241 __alloc_pages_slowpath+0xdcc/0x1290 __alloc_pages_slowpath at mm/page_alloc.c:4512 __alloc_pages_nodemask+0x3bb/0x450 alloc_pages_vma+0x8a/0x2c0 do_anonymous_page+0x16e/0x6f0 __handle_mm_fault+0xcd5/0xd40 handle_mm_fault+0xfc/0x2f0 do_page_fault+0x263/0x6f9 page_fault+0x34/0x40
1 lock held by mtest01/7454:
#0: ffff9f425afe8808 (&mm->mmap_sem#2){++++}, at:
do_page_fault+0x143/0x6f9 do_user_addr_fault at arch/x86/mm/fault.c:1405 (inlined by) do_page_fault at arch/x86/mm/fault.c:1539 irq event stamp: 6944085 count_memcg_event_mm+0x1a6/0x270 count_memcg_event_mm+0x119/0x270 __do_softirq+0x34c/0x57c irq_exit+0xa2/0xc0
read to 0xffff9f427ffff2dc of 4 bytes by task 7472 on cpu 38:
wakeup_kswapd+0xc8/0x400 wake_all_kswapds+0x59/0xc0 __alloc_pages_slowpath+0xdcc/0x1290 __alloc_pages_nodemask+0x3bb/0x450 alloc_pages_vma+0x8a/0x2c0 do_anonymous_page+0x16e/0x6f0 __handle_mm_fault+0xcd5/0xd40 handle_mm_fault+0xfc/0x2f0 do_page_fault+0x263/0x6f9 page_fault+0x34/0x40
1 lock held by mtest01/7472:
#0: ffff9f425a9ac148 (&mm->mmap_sem#2){++++}, at:
do_page_fault+0x143/0x6f9 irq event stamp: 6793561 count_memcg_event_mm+0x1a6/0x270 count_memcg_event_mm+0x119/0x270 __do_softirq+0x34c/0x57c irq_exit+0xa2/0xc0 BUG: KCSAN: data-race in kswapd / wakeup_kswapd
write to 0xffff90973ffff2dc of 4 bytes by task 820 on cpu 6:
kswapd+0x27c/0x8d0 kthread+0x1e0/0x200 ret_from_fork+0x27/0x50
read to 0xffff90973ffff2dc of 4 bytes by task 6299 on cpu 0:
wakeup_kswapd+0xf3/0x450 wake_all_kswapds+0x59/0xc0 __alloc_pages_slowpath+0xdcc/0x1290 __alloc_pages_nodemask+0x3bb/0x450 alloc_pages_vma+0x8a/0x2c0 do_anonymous_page+0x170/0x700 __handle_mm_fault+0xc9f/0xd00 handle_mm_fault+0xfc/0x2f0 do_page_fault+0x263/0x6f9 page_fault+0x34/0x40
--- mm/vmscan.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-)
mm/vmscan.c +26 -19
@@ -3168,8 +3168,9 @@ static bool allow_direct_reclaim(pg_data_t *pgdat)/* kswapd must be awake if processes are being throttled */ if (!wmark_ok &&waitqueue_active (&pgdat->kswapd_wait)) { - pgdat->kswapd_classzone_idx =min (pgdat->kswapd_classzone_idx, - (enum zone_type )ZONE_NORMAL ); +if (READ_ONCE (pgdat->kswapd_classzone_idx) >ZONE_NORMAL ) +WRITE_ONCE (pgdat->kswapd_classzone_idx,ZONE_NORMAL ); +wake_up_interruptible (&pgdat->kswapd_wait); }
@@ -3801,9 +3802,9 @@ out:static enum zone_type kswapd_classzone_idx (pg_data_t *pgdat,enum zone_type prev_classzone_idx) { -if (pgdat->kswapd_classzone_idx ==MAX_NR_ZONES ) -return prev_classzone_idx; -return pgdat->kswapd_classzone_idx; +enum zone_type curr_idx =READ_ONCE (pgdat->kswapd_classzone_idx); + +return curr_idx ==MAX_NR_ZONES ? prev_classzone_idx : curr_idx; } static void kswapd_try_to_sleep(pg_data_t *pgdat, int alloc_order, int reclaim_order,
@@ -3847,8 +3848,11 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int alloc_order, int reclaim_o* the previous request that slept prematurely. */ if (remaining) { - pgdat->kswapd_classzone_idx =kswapd_classzone_idx (pgdat, classzone_idx); - pgdat->kswapd_order =max (pgdat->kswapd_order, reclaim_order); +WRITE_ONCE (pgdat->kswapd_classzone_idx, +kswapd_classzone_idx (pgdat, classzone_idx)); + +if (READ_ONCE (pgdat->kswapd_order) < reclaim_order) +WRITE_ONCE (pgdat->kswapd_order, reclaim_order); }finish_wait (&pgdat->kswapd_wait, &wait);
@@ -3925,12 +3929,12 @@ static int kswapd(void *p) tsk->flags |=PF_MEMALLOC |PF_SWAPWRITE |PF_KSWAPD ;set_freezable (); - pgdat->kswapd_order =0 ; - pgdat->kswapd_classzone_idx =MAX_NR_ZONES ; +WRITE_ONCE (pgdat->kswapd_order,0 ); +WRITE_ONCE (pgdat->kswapd_classzone_idx,MAX_NR_ZONES );for ( ; ; ) {bool ret; - alloc_order = reclaim_order = pgdat->kswapd_order; + alloc_order = reclaim_order =READ_ONCE (pgdat->kswapd_order); classzone_idx =kswapd_classzone_idx (pgdat, classzone_idx); kswapd_try_sleep:
@@ -3938,10 +3942,10 @@ kswapd_try_sleep: classzone_idx);/* Read the new order and classzone_idx */ - alloc_order = reclaim_order = pgdat->kswapd_order; + alloc_order = reclaim_order =READ_ONCE (pgdat->kswapd_order); classzone_idx =kswapd_classzone_idx (pgdat, classzone_idx); - pgdat->kswapd_order =0 ; - pgdat->kswapd_classzone_idx =MAX_NR_ZONES ; +WRITE_ONCE (pgdat->kswapd_order,0 ); +WRITE_ONCE (pgdat->kswapd_classzone_idx,MAX_NR_ZONES ); ret =try_to_freeze ();if (kthread_should_stop ())
@@ -3985,20 +3989,23 @@ void wakeup_kswapd(struct zone *zone, gfp_t gfp_flags, int order, enum zone_type classzone_idx) {pg_data_t *pgdat; +enum zone_type curr_idx;if (!managed_zone (zone))return ;if (!cpuset_zone_allowed (zone, gfp_flags))return ; + pgdat = zone->zone_pgdat; + curr_idx =READ_ONCE (pgdat->kswapd_classzone_idx); + +if (curr_idx ==MAX_NR_ZONES || curr_idx < classzone_idx) +WRITE_ONCE (pgdat->kswapd_classzone_idx, classzone_idx); + +if (READ_ONCE (pgdat->kswapd_order) < order) +WRITE_ONCE (pgdat->kswapd_order, order); -if (pgdat->kswapd_classzone_idx ==MAX_NR_ZONES ) - pgdat->kswapd_classzone_idx = classzone_idx; -else - pgdat->kswapd_classzone_idx =max (pgdat->kswapd_classzone_idx, - classzone_idx); - pgdat->kswapd_order =max (pgdat->kswapd_order, order);if (!waitqueue_active (&pgdat->kswapd_wait))return ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 223/388 SUNRPC: Dont start a timer on an already queued rpc task
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
[ Upstream commit 1fab7dc477241c12f977955aa6baea7938b6f08d ]
Move the test for whether a task is already queued to prevent corruption of the timer list in __rpc_sleep_on_priority_timeout().
--- net/sunrpc/sched.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
net/sunrpc/sched.c +13 -6
@@ -204,10 +204,6 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,struct rpc_task *task, unsigned char queue_priority) { -WARN_ON_ONCE (RPC_IS_QUEUED (task )); -if (RPC_IS_QUEUED (task)) -return ; - INIT_LIST_HEAD(&task->u.tk_wait.timer_list);if (RPC_IS_PRIORITY (queue))__rpc_add_wait_queue_priority (queue, task, queue_priority);
@@ -382,7 +378,7 @@ static void rpc_make_runnable(struct workqueue_struct *wq,* NB: An RPC task will only receive interrupt-driven events as long * as it's on a wait queue. */ -static void __rpc_sleep_on_priority (struct rpc_wait_queue *q, +static void __rpc_do_sleep_on_priority (struct rpc_wait_queue *q,struct rpc_task *task,unsigned char queue_priority) {
@@ -395,12 +391,23 @@ static void __rpc_sleep_on_priority(struct rpc_wait_queue *q, } +static void __rpc_sleep_on_priority (struct rpc_wait_queue *q, +struct rpc_task *task, +unsigned char queue_priority) +{ +if (WARN_ON_ONCE (RPC_IS_QUEUED (task))) +return ; +__rpc_do_sleep_on_priority (q, task, queue_priority); +} +static void __rpc_sleep_on_priority_timeout (struct rpc_wait_queue *q,struct rpc_task *task,unsigned long timeout,unsigned char queue_priority) { +if (WARN_ON_ONCE (RPC_IS_QUEUED (task))) +return ;if (time_is_after_jiffies (timeout)) { -__rpc_sleep_on_priority (q, task, queue_priority); +__rpc_do_sleep_on_priority (q, task, queue_priority);__rpc_add_timer (q, task, timeout); }else task->tk_status = -ETIMEDOUT ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 224/388 nvmet-rdma: fix double free of rdma queue
In reply to Greg Kroah-HartmanFrom: Israel Rukshin <[email protected]>
[ Upstream commit 21f9024355e58772ec5d7fc3534aa5e29d72a8b6 ]
In case rdma accept fails at nvmet_rdma_queue_connect(), release work is scheduled. Later on, a new RDMA CM event may arrive since we didn't destroy the cm-id and call nvmet_rdma_queue_connect_fail(), which schedule another release work. This will cause calling nvmet_rdma_free_queue twice. To fix this we implicitly destroy the cm_id with non-zero ret code, which guarantees that new rdma_cm events will not arrive afterwards. Also add a qp pointer to nvmet_rdma_queue structure, so we can use it when the cm_id pointer is NULL or was destroyed.
--- drivers/nvme/target/rdma.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)
drivers/nvme/target/rdma.c +18 -12
@@ -75,6 +75,7 @@ enum nvmet_rdma_queue_state {struct nvmet_rdma_queue {struct rdma_cm_id *cm_id; +struct ib_qp *qp;struct nvmet_port *port;struct ib_cq *cq;atomic_t sq_wr_avail;
@@ -464,7 +465,7 @@ static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev,if (ndev->srq) ret =ib_post_srq_recv (ndev->srq, &cmd->wr,NULL );else - ret =ib_post_recv (cmd->queue->cm_id->qp, &cmd->wr,NULL ); + ret =ib_post_recv (cmd->queue->qp, &cmd->wr,NULL );if (unlikely (ret))pr_err ("post_recv cmd failed\n" );
@@ -503,7 +504,7 @@ static void nvmet_rdma_release_rsp(struct nvmet_rdma_rsp *rsp)atomic_add (1 + rsp->n_rdma, &queue->sq_wr_avail);if (rsp->n_rdma) { -rdma_rw_ctx_destroy (&rsp->rw, queue->cm_id->qp, +rdma_rw_ctx_destroy (&rsp->rw, queue->qp, queue->cm_id->port_num, rsp->req.sg, rsp->req.sg_cnt,nvmet_data_dir (&rsp->req)); }
@@ -587,7 +588,7 @@ static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc)WARN_ON (rsp->n_rdma <=0 );atomic_add (rsp->n_rdma, &queue->sq_wr_avail); -rdma_rw_ctx_destroy (&rsp->rw, queue->cm_id->qp, +rdma_rw_ctx_destroy (&rsp->rw, queue->qp, queue->cm_id->port_num, rsp->req.sg, rsp->req.sg_cnt,nvmet_data_dir (&rsp->req)); rsp->n_rdma =0 ;
@@ -742,7 +743,7 @@ static bool nvmet_rdma_execute_command(struct nvmet_rdma_rsp *rsp) }if (nvmet_rdma_need_data_in (rsp)) { -if (rdma_rw_ctx_post (&rsp->rw, queue->cm_id->qp, +if (rdma_rw_ctx_post (&rsp->rw, queue->qp, queue->cm_id->port_num, &rsp->read_cqe,NULL ))nvmet_req_complete (&rsp->req,NVME_SC_DATA_XFER_ERROR ); }else {
@@ -1025,6 +1026,7 @@ static int nvmet_rdma_create_queue_ib(struct nvmet_rdma_queue *queue)pr_err ("failed to create_qp ret= %d\n" , ret); goto err_destroy_cq; } + queue->qp = queue->cm_id->qp;atomic_set (&queue->sq_wr_avail, qp_attr.cap.max_send_wr);
@@ -1053,11 +1055,10 @@ err_destroy_cq:static void nvmet_rdma_destroy_queue_ib (struct nvmet_rdma_queue *queue) { -struct ib_qp *qp = queue->cm_id->qp; - -ib_drain_qp (qp); -rdma_destroy_id (queue->cm_id); -ib_destroy_qp (qp); +ib_drain_qp (queue->qp); +if (queue->cm_id) +rdma_destroy_id (queue->cm_id); +ib_destroy_qp (queue->qp);ib_free_cq (queue->cq); }
@@ -1291,9 +1292,12 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id, ret =nvmet_rdma_cm_accept (cm_id, queue, &event->param.conn);if (ret) { -schedule_work (&queue->release_work); -/* Destroying rdma_cm id is not needed here */ -return 0 ; +/* +* Don't destroy the cm_id in free path, as we implicitly +* destroy the cm_id here with non-zero ret code. +*/ + queue->cm_id =NULL ; + goto free_queue; }mutex_lock (&nvmet_rdma_queue_mutex);
@@ -1302,6 +1306,8 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,return 0 ; +free_queue: +nvmet_rdma_free_queue (queue); put_device:kref_put (&ndev->ref, nvmet_rdma_free_dev);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 225/388 workqueue: Remove the warning in wq_worker_sleeping()
In reply to Greg Kroah-HartmanFrom: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit 62849a9612924a655c67cf6962920544aa5c20db ]
The kernel test robot triggered a warning with the following race:
task-ctx A interrupt-ctx B
worker
-> process_one_work()
-> work_item()
-> schedule();
-> sched_submit_work()
-> wq_worker_sleeping()
-> ->sleeping = 1
atomic_dec_and_test(nr_running)
__schedule(); *interrupt*
async_page_fault()
-> local_irq_enable();
-> schedule();
-> sched_submit_work()
-> wq_worker_sleeping()
-> if (WARN_ON(->sleeping)) return
-> __schedule()
-> sched_update_worker()
-> wq_worker_running()
-> atomic_inc(nr_running);
-> ->sleeping = 0;
-> sched_update_worker()
-> wq_worker_running()
if (!->sleeping) returnIn this context the warning is pointless everything is fine. An interrupt before wq_worker_sleeping() will perform the ->sleeping assignment (0 -> 1 > 0) twice.
An interrupt after wq_worker_sleeping() will trigger the warning and nr_running will be decremented (by A) and incremented once (only by B, A will skip it). This is the case until the ->sleeping is zeroed again in wq_worker_running().
Remove the WARN statement because this condition may happen. Document that preemption around wq_worker_sleeping() needs to be disabled to protect ->sleeping and not just as an optimisation.
--- kernel/sched/core.c | 3 ++- kernel/workqueue.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-)
kernel/sched/core.c +2 -1
@@ -4199,7 +4199,8 @@ static inline void sched_submit_work(struct task_struct *tsk)* it wants to wake up a task to maintain concurrency. * As this function is called inside the schedule() context, * we disable preemption to avoid it calling schedule() again -* in the possible wakeup of a kworker. +* in the possible wakeup of a kworker and because wq_worker_sleeping() +* requires it. */ if (tsk->flags &PF_WQ_WORKER ) {preempt_disable ();
kernel/workqueue.c +4 -2
@@ -864,7 +864,8 @@ void wq_worker_running(struct task_struct *task)* @task: task going to sleep * * This function is called from schedule() when a busy worker is -* going to sleep. +* going to sleep. Preemption needs to be disabled to protect ->sleeping +* assignment. */ void wq_worker_sleeping (struct task_struct *task) {
@@ -881,7 +882,8 @@ void wq_worker_sleeping(struct task_struct *task) pool = worker->pool; -if (WARN_ON_ONCE (worker->sleeping)) +/* Return if preempted before wq_worker_running() was reached */ +if (worker->sleeping)return ; worker->sleeping =1 ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 226/388 drm/amdgpu/sriov add amdgpu_amdkfd_pre_reset in gpu reset
In reply to Greg Kroah-HartmanFrom: Jack Zhang <[email protected]>
[ Upstream commit 04bef61e5da18c2b301c629a209ccdba4d4c6fbb ]
kfd_pre_reset will free mem_objs allocated by kfd_gtt_sa_allocate
Without this change, sriov tdr code path will never free those allocated memories and get memory leak.
v2:add a bugfix for kiq ring test fail
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ 3 files changed, 8 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +3 -0
@@ -644,6 +644,9 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,uint32_t temp;struct v10_compute_mqd *m =get_mqd (mqd); +if (amdgpu_sriov_vf (adev) && adev->in_gpu_reset) +return 0 ; +#if 0 unsigned long flags;int retry;
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +3 -0
@@ -540,6 +540,9 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,uint32_t temp;struct v9_mqd *m =get_mqd (mqd); +if (amdgpu_sriov_vf (adev) && adev->in_gpu_reset) +return 0 ; +if (adev->in_gpu_reset)return -EIO ;
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +2 -0
@@ -3466,6 +3466,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,if (r)return r; +amdgpu_amdkfd_pre_reset (adev); +/* Resume IP prior to SMC */ r =amdgpu_device_ip_reinit_early_sriov (adev);if (r)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 227/388 mm/mmap.c: initialize align_offset explicitly for vm_unmapped_area
In reply to Greg Kroah-HartmanFrom: Jaewon Kim <[email protected]>
[ Upstream commit 09ef5283fd96ac424ef0e569626f359bf9ab86c9 ]
On passing requirement to vm_unmapped_area, arch_get_unmapped_area and arch_get_unmapped_area_topdown did not set align_offset. Internally on both unmapped_area and unmapped_area_topdown, if info->align_mask is 0, then info->align_offset was meaningless.
But commit df529cabb7a2 ("mm: mmap: add trace point of vm_unmapped_area") always prints info->align_offset even though it is uninitialized.
Fix this uninitialized value issue by setting it to 0 explicitly.
Before:
vm_unmapped_area: addr=0x755b155000 err=0 total_vm=0x15aaf0 flags=0x1 len=0x109000 lo=0x8000 hi=0x75eed48000 mask=0x0 ofs=0x4022
After:
vm_unmapped_area: addr=0x74a4ca1000 err=0 total_vm=0x168ab1 flags=0x1 len=0x9000 lo=0x8000 hi=0x753d94b000 mask=0x0 ofs=0x0
--- mm/mmap.c | 2 ++ 1 file changed, 2 insertions(+)
mm/mmap.c +2 -0
@@ -2126,6 +2126,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, info.low_limit = mm->mmap_base; info.high_limit = mmap_end; info.align_mask =0 ; + info.align_offset =0 ; return vm_unmapped_area(&info); }#endif
@@ -2167,6 +2168,7 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, info.low_limit =max (PAGE_SIZE , mmap_min_addr); info.high_limit =arch_get_mmap_base (addr, mm->mmap_base); info.align_mask =0 ; + info.align_offset =0 ; addr =vm_unmapped_area (&info);/*
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 228/388 ALSA: hda: Skip controller resume if not needed
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
[ Upstream commit c4c8dd6ef807663e42a5f04ea77cd62029eb99fa ]
The HD-audio controller does system-suspend and resume operations by directly calling its helpers __azx_runtime_suspend() and __azx_runtime_resume(). However, in general, we don't have to resume always the device fully at the system resume; typically, if a device has been runtime-suspended, we can leave it to runtime resume.
Usually for achieving this, the driver would call pm_runtime_force_suspend() and pm_runtime_force_resume() pairs in the system suspend and resume ops. Unfortunately, this doesn't work for the resume path in our case. For handling the jack detection at the system resume, a child codec device may need the (literally) forcibly resume even if it's been runtime-suspended, and for that, the controller device must be also resumed even if it's been suspended.
This patch is an attempt to improve the situation. It replaces the direct __azx_runtime_suspend()/_resume() calls with with pm_runtime_force_suspend() and pm_runtime_force_resume() with a slight trick as we've done for the codec side. More exactly:
- azx_has_pm_runtime() check is dropped from azx_runtime_suspend() and azx_runtime_resume(), so that it can be properly executed from the system-suspend/resume path
- The WAKEEN handling depends on the card's power state now; it's set and cleared only for the runtime-suspend
- azx_resume() checks whether any codec may need the forcible resume beforehand. If the forcible resume is required, it does temporary PM refcount up/down for actually triggering the runtime resume.
- A new helper function, hda_codec_need_resume(), is introduced for checking whether the codec needs a forcible runtime-resume, and the existing code is rewritten with that.
--- include/sound/hda_codec.h | 5 +++++ sound/pci/hda/hda_codec.c | 2 +- sound/pci/hda/hda_intel.c | 38 +++++++++++++++++++++++++++----------- 3 files changed, 33 insertions(+), 12 deletions(-)
include/sound/hda_codec.h +5 -0
@@ -494,6 +494,11 @@ void snd_hda_update_power_acct(struct hda_codec *codec);static inline void snd_hda_set_power_save (struct hda_bus *bus,int delay) {}#endif +static inline bool hda_codec_need_resume (struct hda_codec *codec) +{ +return !codec->relaxed_resume && codec->jacktbl.used; +} +#ifdef CONFIG_SND_HDA_PATCH_LOADER /* * patch firmware
sound/pci/hda/hda_codec.c +1 -1
@@ -2958,7 +2958,7 @@ static int hda_codec_runtime_resume(struct device *dev)static int hda_codec_force_resume (struct device *dev) {struct hda_codec *codec =dev_to_hda_codec (dev); -bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used; +bool forced_resume =hda_codec_need_resume (codec);int ret;/* The get/put pair below enforces the runtime resume even if the
sound/pci/hda/hda_intel.c +27 -11
@@ -1025,7 +1025,7 @@ static int azx_suspend(struct device *dev) chip = card->private_data; bus =azx_bus (chip);snd_power_change_state (card, SNDRV_CTL_POWER_D3hot); -__azx_runtime_suspend (chip); +pm_runtime_force_suspend (dev);if (bus->irq >=0 ) {free_irq (bus->irq, chip); bus->irq =-1 ;
@@ -1041,7 +1041,9 @@ static int azx_suspend(struct device *dev)static int azx_resume (struct device *dev) {struct snd_card *card =dev_get_drvdata (dev); +struct hda_codec *codec;struct azx *chip; +bool forced_resume = false;if (!azx_is_pm_ready (card))return 0 ;
@@ -1052,7 +1054,20 @@ static int azx_resume(struct device *dev) chip->msi =0 ;if (azx_acquire_irq (chip,1 ) <0 )return -EIO ; -__azx_runtime_resume (chip, false); + +/* check for the forced resume */ +list_for_each_codec (codec, &chip->bus) { +if (hda_codec_need_resume (codec)) { + forced_resume = true; +break ; + } + } + +if (forced_resume) +pm_runtime_get_noresume (dev); +pm_runtime_force_resume (dev); +if (forced_resume) +pm_runtime_put (dev);snd_power_change_state (card,SNDRV_CTL_POWER_D0 );trace_azx_resume (chip);
@@ -1099,12 +1114,12 @@ static int azx_runtime_suspend(struct device *dev)if (!azx_is_pm_ready (card))return 0 ; chip = card->private_data; -if (!azx_has_pm_runtime (chip)) -return 0 ;/* enable controller wake up event */ -azx_writew (chip,WAKEEN ,azx_readw (chip,WAKEEN ) | -STATESTS_INT_MASK ); +if (snd_power_get_state (card) ==SNDRV_CTL_POWER_D0 ) { +azx_writew (chip,WAKEEN ,azx_readw (chip,WAKEEN ) | +STATESTS_INT_MASK ); + }__azx_runtime_suspend (chip);trace_azx_runtime_suspend (chip);
@@ -1115,17 +1130,18 @@ static int azx_runtime_resume(struct device *dev) {struct snd_card *card =dev_get_drvdata (dev);struct azx *chip; +bool from_rt =snd_power_get_state (card) ==SNDRV_CTL_POWER_D0 ;if (!azx_is_pm_ready (card))return 0 ; chip = card->private_data; -if (!azx_has_pm_runtime (chip)) -return 0 ; -__azx_runtime_resume (chip, true); +__azx_runtime_resume (chip, from_rt);/* disable controller Wake Up event*/ -azx_writew (chip,WAKEEN ,azx_readw (chip,WAKEEN ) & - ~STATESTS_INT_MASK ); +if (from_rt) { +azx_writew (chip,WAKEEN ,azx_readw (chip,WAKEEN ) & + ~STATESTS_INT_MASK ); + }trace_azx_runtime_resume (chip);return 0 ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 229/388 scsi: qedi: Fix termination timeouts in session logout
In reply to Greg Kroah-HartmanFrom: Nilesh Javali <[email protected]>
[ Upstream commit b9b97e6903032ec56e6dcbe137a9819b74a17fea ]
The destroy connection ramrod timed out during session logout. Fix the wait delay for graceful vs abortive termination as per the FW requirements.
--- drivers/scsi/qedi/qedi_iscsi.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/scsi/qedi/qedi_iscsi.c +3 -0
@@ -1062,6 +1062,9 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)break ; } +if (!abrt_conn) + wait_delay += qedi->pf_params.iscsi_pf_params.two_msl_timer; + qedi_ep->state =EP_STATE_DISCONN_START ; ret = qedi_ops->destroy_conn (qedi->cdev, qedi_ep->handle, abrt_conn);if (ret) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 230/388 serial: uartps: Wait for tx_empty in console setup
In reply to Greg Kroah-HartmanFrom: Raviteja Narayanam <[email protected]>
[ Upstream commit 42e11948ddf68b9f799cad8c0ddeab0a39da33e8 ]
On some platforms, the log is corrupted while console is being registered. It is observed that when set_termios is called, there are still some bytes in the FIFO to be transmitted.
So, wait for tx_empty inside cdns_uart_console_setup before calling set_termios.
--- drivers/tty/serial/xilinx_uartps.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/tty/serial/xilinx_uartps.c +8 -0
@@ -1248,6 +1248,7 @@ static int cdns_uart_console_setup(struct console *co, char *options)int bits =8 ;int parity ='n' ;int flow ='n' ; +unsigned long time_out;if (!port->membase) { pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
@@ -1258,6 +1259,13 @@ static int cdns_uart_console_setup(struct console *co, char *options)if (options)uart_parse_options (options, &baud, &parity, &bits, &flow); +/* Wait for tx_empty before setting up the console */ + time_out = jiffies +usecs_to_jiffies (TX_TIMEOUT ); + +while (time_before (jiffies, time_out) && +cdns_uart_tx_empty (port) !=TIOCSER_TEMT ) +cpu_relax (); +return uart_set_options (port, co, baud, parity, bits, flow); }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 231/388 btrfs: fix setting last_trans for reloc roots
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
[ Upstream commit aec7db3b13a07d515c15ada752a7287a44a79ea0 ]
I made a mistake with my previous fix, I assumed that we didn't need to mess with the reloc roots once we were out of the part of relocation where we are actually moving the extents.
The subtle thing that I missed is that btrfs_init_reloc_root() also updates the last_trans for the reloc root when we do btrfs_record_root_in_trans() for the corresponding fs_root. I've added a comment to make sure future me doesn't make this mistake again.
This showed up as a WARN_ON() in btrfs_copy_root() because our last_trans didn't == the current transid. This could happen if we snapshotted a fs root with a reloc root after we set rc->create_reloc_tree = 0, but before we actually merge the reloc root.
Worth mentioning that the regression produced the following warning when running snapshot creation and balance in parallel:
BTRFS info (device sdc): relocating block group 30408704 flags metadata|dup
------------[ cut here ]------------ WARNING: CPU: 0 PID: 12823 at fs/btrfs/ctree.c:191 btrfs_copy_root+0x26f/0x430 [btrfs] CPU: 0 PID: 12823 Comm: btrfs Tainted: G W 5.6.0-rc7-btrfs-next-58 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 RIP: 0010:btrfs_copy_root+0x26f/0x430 [btrfs] RSP: 0018:ffffb96e044279b8 EFLAGS: 00010202 RAX: 0000000000000009 RBX: ffff9da70bf61000 RCX: ffffb96e04427a48 RDX: ffff9da733a770c8 RSI: ffff9da70bf61000 RDI: ffff9da694163818 RBP: ffff9da733a770c8 R08: fffffffffffffff8 R09: 0000000000000002 R10: ffffb96e044279a0 R11: 0000000000000000 R12: ffff9da694163818 R13: fffffffffffffff8 R14: ffff9da6d2512000 R15: ffff9da714cdac00 FS: 00007fdeacf328c0(0000) GS:ffff9da735e00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055a2a5b8a118 CR3: 00000001eed78002 CR4: 00000000003606f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ? create_reloc_root+0x49/0x2b0 [btrfs] ? kmem_cache_alloc_trace+0xe5/0x200 create_reloc_root+0x8b/0x2b0 [btrfs] btrfs_reloc_post_snapshot+0x96/0x5b0 [btrfs] create_pending_snapshot+0x610/0x1010 [btrfs] create_pending_snapshots+0xa8/0xd0 [btrfs] btrfs_commit_transaction+0x4c7/0xc50 [btrfs] ? btrfs_mksubvol+0x3cd/0x560 [btrfs] btrfs_mksubvol+0x455/0x560 [btrfs] __btrfs_ioctl_snap_create+0x15f/0x190 [btrfs] btrfs_ioctl_snap_create_v2+0xa4/0xf0 [btrfs] ? mem_cgroup_commit_charge+0x6e/0x540 btrfs_ioctl+0x12d8/0x3760 [btrfs] ? do_raw_spin_unlock+0x49/0xc0 ? _raw_spin_unlock+0x29/0x40 ? __handle_mm_fault+0x11b3/0x14b0 ? ksys_ioctl+0x92/0xb0 ksys_ioctl+0x92/0xb0 ? trace_hardirqs_off_thunk+0x1a/0x1c __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x5c/0x280 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7fdeabd3bdd7
--- fs/btrfs/relocation.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
fs/btrfs/relocation.c +17 -2
@@ -1468,8 +1468,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,int clear_rsv =0 ;int ret; -if (!rc || !rc->create_reloc_tree || - root->root_key.objectid ==BTRFS_TREE_RELOC_OBJECTID ) +if (!rc)return 0 ;/*
@@ -1479,12 +1478,28 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,if (reloc_root_is_dead (root))return 0 ; +/* +* This is subtle but important. We do not do +* record_root_in_transaction for reloc roots, instead we record their +* corresponding fs root, and then here we update the last trans for the +* reloc root. This means that we have to do this for the entire life +* of the reloc root, regardless of which stage of the relocation we are +* in. +*/ if (root->reloc_root) { reloc_root = root->reloc_root; reloc_root->last_trans = trans->transid;return 0 ; } +/* +* We are merging reloc roots, we do not need new reloc trees. Also +* reloc trees never need their own reloc tree. +*/ +if (!rc->create_reloc_tree || + root->root_key.objectid ==BTRFS_TREE_RELOC_OBJECTID ) +return 0 ; +if (!trans->reloc_reserved) { rsv = trans->block_rsv; trans->block_rsv = rc->block_rsv;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 232/388 KVM: Remove CREATE_IRQCHIP/SET_PIT2 race
In reply to Greg Kroah-HartmanFrom: Steve Rutherford <[email protected]>
[ Upstream commit 7289fdb5dcdbc5155b5531529c44105868a762f2 ]
Fixes a NULL pointer dereference, caused by the PIT firing an interrupt before the interrupt table has been initialized.
SET_PIT2 can race with the creation of the IRQchip. In particular, if SET_PIT2 is called with a low PIT timer period (after the creation of the IOAPIC, but before the instantiation of the irq routes), the PIT can fire an interrupt at an uninitialized table.
Message-Id: <[email protected]>
--- arch/x86/kvm/x86.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +8 -2
@@ -5050,10 +5050,13 @@ set_identity_unlock: r = -EFAULT ;if (copy_from_user (&u.ps, argp,sizeof (u.ps))) goto out; +mutex_lock (&kvm->lock); r = -ENXIO ;if (!kvm->arch.vpit) - goto out; + goto set_pit_out; r =kvm_vm_ioctl_set_pit (kvm, &u.ps); +set_pit_out: +mutex_unlock (&kvm->lock);break ; }case KVM_GET_PIT2 : {
@@ -5073,10 +5076,13 @@ set_identity_unlock: r = -EFAULT ;if (copy_from_user (&u.ps2, argp,sizeof (u.ps2))) goto out; +mutex_lock (&kvm->lock); r = -ENXIO ;if (!kvm->arch.vpit) - goto out; + goto set_pit2_out; r =kvm_vm_ioctl_set_pit2 (kvm, &u.ps2); +set_pit2_out: +mutex_unlock (&kvm->lock);break ; }case KVM_REINJECT_CONTROL : {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 233/388 perf stat: Force error in fallback on :k events
In reply to Greg Kroah-HartmanFrom: Stephane Eranian <[email protected]>
[ Upstream commit bec49a9e05db3dbdca696fa07c62c52638fb6371 ]
When it is not possible for a non-privilege perf command to monitor at the kernel level (:k), the fallback code forces a :u. That works if the event was previously monitoring both levels. But if the event was already constrained to kernel only, then it does not make sense to restrict it to user only.
Given the code works by exclusion, a kernel only event would have:
attr->exclude_user = 1
The fallback code would add:
attr->exclude_kernel = 1
In the end the end would not monitor in either the user level or kernel level. In other words, it would count nothing.
An event programmed to monitor kernel only cannot be switched to user only without seriously warning the user.
This patch forces an error in this case to make it clear the request cannot really be satisfied.
Behavior with paranoid 1:
$ sudo bash -c "echo 1 > /proc/sys/kernel/perf_event_paranoid" $ perf stat -e cycles:k sleep 1
Performance counter stats for 'sleep 1':
1,520,413 cycles:k
1.002361664 seconds time elapsed
0.002480000 seconds user
0.000000000 seconds sysOld behavior with paranoid 2:
$ sudo bash -c "echo 2 > /proc/sys/kernel/perf_event_paranoid" $ perf stat -e cycles:k sleep 1 Performance counter stats for 'sleep 1':
0 cycles:ku
1.002358127 seconds time elapsed
0.002384000 seconds user
0.000000000 seconds sysNew behavior with paranoid 2:
$ sudo bash -c "echo 2 > /proc/sys/kernel/perf_event_paranoid" $ perf stat -e cycles:k sleep 1 Error: You may not have permission to collect stats.
Consider tweaking /proc/sys/kernel/perf_event_paranoid, which controls use of the performance events system by unprivileged users (without CAP_PERFMON or CAP_SYS_ADMIN).
The current value is 2:
-1: Allow use of (almost) all events by all users
Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
Quoted 1 line
= 0: Disallow ftrace function tracepoint by users without
CAP_PERFMONorCAP_SYS_ADMIN
Disallow raw tracepoint access by users without CAP_SYS_PERFMON or CAP_SYS_ADMIN
Quoted 2 lines
= 1: Disallow CPU event access by users without
CAP_PERFMONorCAP_SYS_ADMIN= 2: Disallow kernel profiling by users withoutCAP_PERFMONorCAP_SYS_ADMIN
To make this setting permanent, edit /etc/sysctl.conf too, e.g.:
kernel.perf_event_paranoid = -1
v2 of this patch addresses the review feedback from [email protected].
--- tools/perf/util/evsel.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/evsel.c +4 -0
@@ -2358,6 +2358,10 @@ bool perf_evsel__fallback(struct evsel *evsel, int err,char *new_name;const char *sep =":" ; +/* If event has exclude user then don't exclude kernel. */ +if (evsel->core.attr.exclude_user) +return false; +/* Is there already the separator in the name. */ if (strchr (name,'/' ) ||strchr (name,':' ))
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 234/388 bdev: Reduce time holding bd_mutex in sync in blkdev_close()
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
[ Upstream commit b849dd84b6ccfe32622988b79b7b073861fcf9f7 ]
While trying to "dd" to the block device for a USB stick, I encountered a hung task warning (blocked for > 120 seconds). I managed to come up with an easy way to reproduce this on my system (where /dev/sdb is the block device for my USB stick) with:
while true; do dd if=/dev/zero of=/dev/sdb bs=4M; done
With my reproduction here are the relevant bits from the hung task detector:
INFO: task udevd:294 blocked for more than 122 seconds. ... udevd D 0 294 1 0x00400008 Call trace: ... mutex_lock_nested+0x40/0x50 __blkdev_get+0x7c/0x3d4 blkdev_get+0x118/0x138 blkdev_open+0x94/0xa8 do_dentry_open+0x268/0x3a0 vfs_open+0x34/0x40 path_openat+0x39c/0xdf4 do_filp_open+0x90/0x10c do_sys_open+0x150/0x3c8 ...
...
Showing all locks held in the system:
...
1 lock held by dd/2798:
#0: ffffff814ac1a3b8 (&bdev->bd_mutex){+.+.}, at: __blkdev_put+0x50/0x204
...
dd D 0 2798 2764 0x00400208
Call trace:
...
schedule+0x8c/0xbc
io_schedule+0x1c/0x40
wait_on_page_bit_common+0x238/0x338
__lock_page+0x5c/0x68
write_cache_pages+0x194/0x500
generic_writepages+0x64/0xa4
blkdev_writepages+0x24/0x30
do_writepages+0x48/0xa8
__filemap_fdatawrite_range+0xac/0xd8
filemap_write_and_wait+0x30/0x84
__blkdev_put+0x88/0x204
blkdev_put+0xc4/0xe4
blkdev_close+0x28/0x38
__fput+0xe0/0x238
____fput+0x1c/0x28
task_work_run+0xb0/0xe4
do_notify_resume+0xfc0/0x14bc
work_pending+0x8/0x14The problem appears related to the fact that my USB disk is terribly slow and that I have a lot of RAM in my system to cache things. Specifically my writes seem to be happening at ~15 MB/s and I've got ~4 GB of RAM in my system that can be used for buffering. To write 4 GB of buffer to disk thus takes ~4000 MB / ~15 MB/s = ~267 seconds.
The 267 second number is a problem because in __blkdev_put() we call sync_blockdev() while holding the bd_mutex. Any other callers who want the bd_mutex will be blocked for the whole time.
The problem is made worse because I believe blkdev_put() specifically tells other tasks (namely udev) to go try to access the device at right around the same time we're going to hold the mutex for a long time.
Putting some traces around this (after disabling the hung task detector), I could confirm:
dd: 437.608600: __blkdev_put() right before sync_blockdev() for sdb
udevd: 437.623901: blkdev_open() right before blkdev_get() for sdb
dd: 661.468451: __blkdev_put() right after sync_blockdev() for sdb
udevd: 663.820426: blkdev_open() right after blkdev_get() for sdb
A simple fix for this is to realize that sync_blockdev() works fine if you're not holding the mutex. Also, it's not the end of the world if you sync a little early (though it can have performance impacts). Thus we can make a guess that we're going to need to do the sync and then do it without holding the mutex. We still do one last sync with the mutex but it should be much, much faster.
With this, my hung task warnings for my test case are gone.
--- fs/block_dev.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/block_dev.c +10 -0
@@ -1857,6 +1857,16 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)struct gendisk *disk = bdev->bd_disk;struct block_device *victim =NULL ; +/* +* Sync early if it looks like we're the last one. If someone else +* opens the block device between now and the decrement of bd_openers +* then we did a sync that we didn't need to, but that's not the end +* of the world and we want to avoid long (could be several minute) +* syncs while holding the mutex. +*/ +if (bdev->bd_openers ==1 ) +sync_blockdev (bdev); +mutex_lock_nested (&bdev->bd_mutex, for_part);if (for_part) bdev->bd_part_count--;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 235/388 drivers: char: tlclk.c: Avoid data race between init and interrupt handler
In reply to Greg Kroah-HartmanFrom: Madhuparna Bhowmik <[email protected]>
[ Upstream commit 44b8fb6eaa7c3fb770bf1e37619cdb3902cca1fc ]
After registering character device the file operation callbacks can be called. The open callback registers interrupt handler. Therefore interrupt handler can execute in parallel with rest of the init function. To avoid such data race initialize telclk_interrupt variable and struct alarm_events before registering character device.
Found by Linux Driver Verification project (linuxtesting.org).
--- drivers/char/tlclk.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
drivers/char/tlclk.c +10 -7
@@ -777,17 +777,21 @@ static int __init tlclk_init(void) {int ret; + telclk_interrupt = (inb (TLCLK_REG7 ) &0x0f ); + + alarm_events =kzalloc (sizeof (struct tlclk_alarms ),GFP_KERNEL ); +if (!alarm_events) { + ret = -ENOMEM ; + goto out1; + } + ret =register_chrdev (tlclk_major,"telco_clock" , &tlclk_fops);if (ret <0 ) {printk (KERN_ERR "tlclk: can't get major %d.\n" , tlclk_major); +kfree (alarm_events);return ret; } tlclk_major = ret; - alarm_events =kzalloc (sizeof (struct tlclk_alarms ),GFP_KERNEL ); -if (!alarm_events) { - ret = -ENOMEM ; - goto out1; - }/* Read telecom clock IRQ number (Set by BIOS) */ if (!request_region (TLCLK_BASE ,8 ,"telco_clock" )) {
@@ -796,7 +800,6 @@ static int __init tlclk_init(void) ret = -EBUSY ; goto out2; } - telclk_interrupt = (inb (TLCLK_REG7 ) &0x0f );if (0x0F == telclk_interrupt ) {/* not MCPBL0010 ? */ printk(KERN_ERR "telclk_interrupt = 0x%x non-mcpbl0010 hw.\n",
@@ -837,8 +840,8 @@ out3:release_region (TLCLK_BASE ,8 ); out2:kfree (alarm_events); -out1:unregister_chrdev (tlclk_major,"telco_clock" ); +out1:return ret; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 236/388 KVM: arm64: vgic-v3: Retire all pending LPIs on vcpu destroy
In reply to Greg Kroah-HartmanFrom: Zenghui Yu <[email protected]>
[ Upstream commit 969ce8b5260d8ec01e6f1949d2927a86419663ce ]
It's likely that the vcpu fails to handle all virtual interrupts if userspace decides to destroy it, leaving the pending ones stay in the ap_list. If the un-handled one is a LPI, its vgic_irq structure will be eventually leaked because of an extra refcount increment in vgic_queue_irq_unlock().
This was detected by kmemleak on almost every guest destroy, the backtrace is as follows:
unreferenced object 0xffff80725aed5500 (size 128):
comm "CPU 5/KVM", pid 40711, jiffies 4298024754 (age 166366.512s) hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 08 01 a9 73 6d 80 ff ff ...........sm... c8 61 ee a9 00 20 ff ff 28 1e 55 81 6c 80 ff ff .a... ..(.U.l... backtrace:
[<000000004bcaa122>] kmem_cache_alloc_trace+0x2dc/0x418 [<0000000069c7dabb>] vgic_add_lpi+0x88/0x418 [<00000000bfefd5c5>] vgic_its_cmd_handle_mapi+0x4dc/0x588 [<00000000cf993975>] vgic_its_process_commands.part.5+0x484/0x1198 [<000000004bd3f8e3>] vgic_its_process_commands+0x50/0x80 [<00000000b9a65b2b>] vgic_mmio_write_its_cwriter+0xac/0x108 [<0000000009641ebb>] dispatch_mmio_write+0xd0/0x188 [<000000008f79d288>] __kvm_io_bus_write+0x134/0x240 [<00000000882f39ac>] kvm_io_bus_write+0xe0/0x150 [<0000000078197602>] io_mem_abort+0x484/0x7b8 [<0000000060954e3c>] kvm_handle_guest_abort+0x4cc/0xa58 [<00000000e0d0cd65>] handle_exit+0x24c/0x770 [<00000000b44a7fad>] kvm_arch_vcpu_ioctl_run+0x460/0x1988 [<0000000025fb897c>] kvm_vcpu_ioctl+0x4f8/0xee0 [<000000003271e317>] do_vfs_ioctl+0x160/0xcd8 [<00000000e7f39607>] ksys_ioctl+0x98/0xd8
Fix it by retiring all pending LPIs in the ap_list on the destroy path.
p.s. I can also reproduce it on a normal guest shutdown. It is because userspace still send LPIs to vcpu (through KVM_SIGNAL_MSI ioctl) while the guest is being shutdown and unable to handle it. A little strange though and haven't dig further...
--- virt/kvm/arm/vgic/vgic-init.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
virt/kvm/arm/vgic/vgic-init.c +8 -2
@@ -358,6 +358,12 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) {struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; +/* +* Retire all pending LPIs on this vcpu anyway as we're +* going to destroy it. +*/ +vgic_flush_pending_lpis (vcpu); +INIT_LIST_HEAD (&vgic_cpu->ap_list_head); }
@@ -369,10 +375,10 @@ static void __kvm_vgic_destroy(struct kvm *kvm)vgic_debug_destroy (kvm); -kvm_vgic_dist_destroy (kvm); -kvm_for_each_vcpu (i, vcpu, kvm)kvm_vgic_vcpu_destroy (vcpu); + +kvm_vgic_dist_destroy (kvm); }void kvm_vgic_destroy (struct kvm *kvm)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 237/388 KVM: arm64: vgic-its: Fix memory leak on the error path of vgic_add_lpi()
In reply to Greg Kroah-HartmanFrom: Zenghui Yu <[email protected]>
[ Upstream commit 57bdb436ce869a45881d8aa4bc5dac8e072dd2b6 ]
If we're going to fail out the vgic_add_lpi(), let's make sure the allocated vgic_irq memory is also freed. Though it seems that both cases are unlikely to fail.
--- virt/kvm/arm/vgic/vgic-its.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
virt/kvm/arm/vgic/vgic-its.c +9 -2
@@ -96,14 +96,21 @@ out_unlock:* We "cache" the configuration table entries in our struct vgic_irq's. * However we only have those structs for mapped IRQs, so we read in * the respective config data from memory here upon mapping the LPI. +* +* Should any of these fail, behave as if we couldn't create the LPI +* by dropping the refcount and returning the error. */ ret =update_lpi_config (kvm, irq,NULL , false); -if (ret) +if (ret) { +vgic_put_irq (kvm, irq);return ERR_PTR (ret); + } ret =vgic_v3_lpi_sync_pending_status (kvm, irq); -if (ret) +if (ret) { +vgic_put_irq (kvm, irq);return ERR_PTR (ret); + }return irq; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 238/388 net: openvswitch: use u64 for meter bucket
In reply to Greg Kroah-HartmanFrom: Tonghao Zhang <[email protected]>
[ Upstream commit e57358873bb5d6caa882b9684f59140912b37dde ]
When setting the meter rate to 4+Gbps, there is an overflow, the meters don't work as expected.
--- net/openvswitch/meter.c | 2 +- net/openvswitch/meter.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
net/openvswitch/meter.c +1 -1
@@ -251,7 +251,7 @@ static struct dp_meter *dp_meter_create(struct nlattr **a)* * Start with a full bucket. */ - band->bucket = (band->burst_size + band->rate) *1000 ; + band->bucket = (band->burst_size + band->rate) *1000ULL ; band_max_delta_t = band->bucket / band->rate;if (band_max_delta_t > meter->max_delta_t) meter->max_delta_t = band_max_delta_t;
net/openvswitch/meter.h +1 -1
@@ -23,7 +23,7 @@ struct dp_meter_band {u32 type;u32 rate;u32 burst_size; -u32 bucket;/* 1/1000 packets, or in bits */ +u64 bucket;/* 1/1000 packets, or in bits */ struct ovs_flow_stats stats; };
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 239/388 scsi: aacraid: Fix error handling paths in aac_probe_one()
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit f7854c382240c1686900b2f098b36430c6f5047e ]
If 'scsi_host_alloc()' or 'kcalloc()' fail, 'error' is known to be 0. Set it explicitly to -ENOMEM before branching to the error handling path.
While at it, remove 2 useless assignments to 'error'. These values are overwridden a few lines later.
--- drivers/scsi/aacraid/linit.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/scsi/aacraid/linit.c +8 -4
@@ -1607,7 +1607,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)struct Scsi_Host *shost;struct aac_dev *aac;struct list_head *insert = &aac_devices; -int error = -ENODEV ; +int error;int unique_id =0 ;u64 dmamask;int mask_bits =0 ;
@@ -1632,7 +1632,6 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) error =pci_enable_device (pdev);if (error) goto out; - error = -ENODEV ;if (!(aac_drivers[index].quirks &AAC_QUIRK_SRC )) { error =pci_set_dma_mask (pdev,DMA_BIT_MASK (32 ));
@@ -1664,8 +1663,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)pci_set_master (pdev); shost =scsi_host_alloc (&aac_driver_template,sizeof (struct aac_dev )); -if (!shost) +if (!shost) { + error = -ENOMEM ; goto out_disable_pdev; + } shost->irq = pdev->irq; shost->unique_id = unique_id;
@@ -1690,8 +1691,11 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) aac->fibs =kcalloc (shost->can_queue +AAC_NUM_MGT_FIB ,sizeof (struct fib ),GFP_KERNEL ); -if (!aac->fibs) +if (!aac->fibs) { + error = -ENOMEM ; goto out_free_host; + } +spin_lock_init (&aac->fib_lock);mutex_init (&aac->ioctl_mutex);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 240/388 staging:r8188eu: avoid skb_clone for amsdu to msdu conversion
In reply to Greg Kroah-HartmanFrom: Ivan Safonov <[email protected]>
[ Upstream commit 628cbd971a927abe6388d44320e351c337b331e4 ]
skb clones use same data buffer,
so tail of one skb is corrupted by beginning of next skb.
--- drivers/staging/rtl8188eu/core/rtw_recv.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
drivers/staging/rtl8188eu/core/rtw_recv.c +6 -13
@@ -1525,21 +1525,14 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)/* Allocate new skb for releasing to upper layer */ sub_skb =dev_alloc_skb (nSubframe_Length +12 ); -if (sub_skb) { -skb_reserve (sub_skb,12 ); -skb_put_data (sub_skb, pdata, nSubframe_Length); - }else { - sub_skb =skb_clone (prframe->pkt,GFP_ATOMIC ); -if (sub_skb) { - sub_skb->data = pdata; - sub_skb->len = nSubframe_Length; -skb_set_tail_pointer (sub_skb, nSubframe_Length); - }else { -DBG_88E ("skb_clone() Fail!!! , nr_subframes=%d\n" , nr_subframes); -break ; - } +if (!sub_skb) { +DBG_88E ("dev_alloc_skb() Fail!!! , nr_subframes=%d\n" , nr_subframes); +break ; } +skb_reserve (sub_skb,12 ); +skb_put_data (sub_skb, pdata, nSubframe_Length); + subframes[nr_subframes++] = sub_skb;if (nr_subframes >=MAX_SUBFRAME_COUNT ) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 241/388 sparc64: vcc: Fix error return code in vcc_probe()
In reply to Greg Kroah-HartmanFrom: Wei Yongjun <[email protected]>
[ Upstream commit ff62255a2a5c1228a28f2bb063646f948115a309 ]
Fix to return negative error code -ENOMEM from the error handling case instead of 0, as done elsewhere in this function.
--- drivers/tty/vcc.c | 1 + 1 file changed, 1 insertion(+)
drivers/tty/vcc.c +1 -0
@@ -605,6 +605,7 @@ static int vcc_probe(struct vio_dev *vdev, const struct vio_device_id *id) port->index =vcc_table_add (port);if (port->index ==-1 ) {pr_err ("VCC: no more TTY indices left for allocation\n" ); + rv = -ENOMEM ; goto free_ldc; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 242/388 arm64: cpufeature: Relax checks for AArch32 support at EL[0-2]
In reply to Greg Kroah-HartmanFrom: Will Deacon <[email protected]>
[ Upstream commit 98448cdfe7060dd5491bfbd3f7214ffe1395d58e ]
We don't need to be quite as strict about mismatched AArch32 support, which is good because the friendly hardware folks have been busy mismatching this to their hearts' content.
* We don't care about EL2 or EL3 (there are silly comments concerning the latter, so remove those)
* EL1 support is gated by the ARM64_HAS_32BIT_EL1 capability and handled gracefully when a mismatch occurs
* EL0 support is gated by the ARM64_HAS_32BIT_EL0 capability and handled gracefully when a mismatch occurs
Relax the AArch32 checks to FTR_NONSTRICT.
--- arch/arm64/kernel/cpufeature.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
arch/arm64/kernel/cpufeature.c +3 -7
@@ -160,11 +160,10 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_GIC_SHIFT ,4 ,0 ),S_ARM64_FTR_BITS (FTR_VISIBLE ,FTR_STRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_ASIMD_SHIFT ,4 ,ID_AA64PFR0_ASIMD_NI ),S_ARM64_FTR_BITS (FTR_VISIBLE ,FTR_STRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_FP_SHIFT ,4 ,ID_AA64PFR0_FP_NI ), -/* Linux doesn't care about the EL3 */ ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL3_SHIFT ,4 ,0 ), -ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL2_SHIFT ,4 ,0 ), -ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL1_SHIFT ,4 ,ID_AA64PFR0_EL1_64BIT_ONLY ), -ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL0_SHIFT ,4 ,ID_AA64PFR0_EL0_64BIT_ONLY ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL2_SHIFT ,4 ,0 ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL1_SHIFT ,4 ,ID_AA64PFR0_EL1_64BIT_ONLY ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_LOWER_SAFE ,ID_AA64PFR0_EL0_SHIFT ,4 ,ID_AA64PFR0_EL0_64BIT_ONLY ), ARM64_FTR_END, };
@@ -719,9 +718,6 @@ void update_cpu_features(int cpu, taint |=check_update_ftr_reg (SYS_ID_AA64MMFR2_EL1 , cpu, info->reg_id_aa64mmfr2, boot->reg_id_aa64mmfr2); -/* -* EL3 is not our concern. -*/ taint |=check_update_ftr_reg (SYS_ID_AA64PFR0_EL1 , cpu, info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0); taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu,
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 243/388 sched/fair: Eliminate bandwidth race between throttling and distribution
In reply to Greg Kroah-HartmanFrom: Paul Turner <[email protected]>
[ Upstream commit e98fa02c4f2ea4991dae422ac7e34d102d2f0599 ]
There is a race window in which an entity begins throttling before quota is added to the pool, but does not finish throttling until after we have finished with distribute_cfs_runtime(). This entity is not observed by distribute_cfs_runtime() because it was not on the throttled list at the time that distribution was running. This race manifests as rare period-length statlls for such entities.
Rather than heavy-weight the synchronization with the progress of distribution, we can fix this by aborting throttling if bandwidth has become available. Otherwise, we immediately add the entity to the throttled list so that it can be observed by a subsequent distribution.
Additionally, we can remove the case of adding the throttled entity to the head of the throttled list, and simply always add to the tail. Thanks to 26a8b12747c97, distribute_cfs_runtime() no longer holds onto its own pool of runtime. This means that if we do hit the !assign and distribute_running case, we know that distribution is about to end.
--- kernel/sched/fair.c | 79 +++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 32 deletions(-)
kernel/sched/fair.c +47 -32
@@ -4383,16 +4383,16 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg) }/* returns 0 on failure to allocate runtime */ -static int assign_cfs_rq_runtime (struct cfs_rq *cfs_rq) +static int __assign_cfs_rq_runtime (struct cfs_bandwidth *cfs_b, +struct cfs_rq *cfs_rq,u64 target_runtime) { -struct task_group *tg = cfs_rq->tg; -struct cfs_bandwidth *cfs_b =tg_cfs_bandwidth (tg); -u64 amount =0 , min_amount; +u64 min_amount, amount =0 ; + +lockdep_assert_held (&cfs_b->lock);/* note: this is a positive sum as runtime_remaining <= 0 */ - min_amount =sched_cfs_bandwidth_slice () - cfs_rq->runtime_remaining; + min_amount = target_runtime - cfs_rq->runtime_remaining; -raw_spin_lock (&cfs_b->lock);if (cfs_b->quota ==RUNTIME_INF ) amount = min_amount;else {
@@ -4404,13 +4404,25 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq) cfs_b->idle =0 ; } } -raw_spin_unlock (&cfs_b->lock); cfs_rq->runtime_remaining += amount;return cfs_rq->runtime_remaining >0 ; } +/* returns 0 on failure to allocate runtime */ +static int assign_cfs_rq_runtime (struct cfs_rq *cfs_rq) +{ +struct cfs_bandwidth *cfs_b =tg_cfs_bandwidth (cfs_rq->tg); +int ret; + +raw_spin_lock (&cfs_b->lock); + ret =__assign_cfs_rq_runtime (cfs_b, cfs_rq,sched_cfs_bandwidth_slice ()); +raw_spin_unlock (&cfs_b->lock); + +return ret; +} +static void __account_cfs_rq_runtime (struct cfs_rq *cfs_rq,u64 delta_exec) {/* dock delta_exec before expiring quota (as it could span periods) */
@@ -4499,13 +4511,33 @@ static int tg_throttle_down(struct task_group *tg, void *data)return 0 ; } -static void throttle_cfs_rq (struct cfs_rq *cfs_rq) +static bool throttle_cfs_rq (struct cfs_rq *cfs_rq) {struct rq *rq =rq_of (cfs_rq);struct cfs_bandwidth *cfs_b =tg_cfs_bandwidth (cfs_rq->tg);struct sched_entity *se;long task_delta, idle_task_delta, dequeue =1 ; -bool empty; + +raw_spin_lock (&cfs_b->lock); +/* This will start the period timer if necessary */ +if (__assign_cfs_rq_runtime (cfs_b, cfs_rq,1 )) { +/* +* We have raced with bandwidth becoming available, and if we +* actually throttled the timer might not unthrottle us for an +* entire period. We additionally needed to make sure that any +* subsequent check_cfs_rq_runtime calls agree not to throttle +* us, as we may commit to do cfs put_prev+pick_next, so we ask +* for 1ns of runtime rather than just check cfs_b. +*/ + dequeue =0 ; + }else { +list_add_tail_rcu (&cfs_rq->throttled_list, + &cfs_b->throttled_cfs_rq); + } +raw_spin_unlock (&cfs_b->lock); + +if (!dequeue) +return false;/* Throttle no longer required. */ se = cfs_rq->tg->se[cpu_of (rq_of (cfs_rq))];
@@ -4534,29 +4566,13 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)if (!se)sub_nr_running (rq, task_delta); - cfs_rq->throttled =1 ; - cfs_rq->throttled_clock =rq_clock (rq); -raw_spin_lock (&cfs_b->lock); - empty =list_empty (&cfs_b->throttled_cfs_rq); - -/* -* Add to the _head_ of the list, so that an already-started -* distribute_cfs_runtime will not see us. If disribute_cfs_runtime is -* not running add to the tail so that later runqueues don't get starved. -*/ -if (cfs_b->distribute_running) -list_add_rcu (&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq); -else -list_add_tail_rcu (&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq); -/* -* If we're the first throttled task, make sure the bandwidth -* timer is running. +* Note: distribution will already see us throttled via the +* throttled-list. rq->lock protects completion. */ -if (empty) -start_cfs_bandwidth (cfs_b); - -raw_spin_unlock (&cfs_b->lock); + cfs_rq->throttled =1 ; + cfs_rq->throttled_clock =rq_clock (rq); +return true; }void unthrottle_cfs_rq (struct cfs_rq *cfs_rq)
@@ -4915,8 +4931,7 @@ static bool check_cfs_rq_runtime(struct cfs_rq *cfs_rq)if (cfs_rq_throttled (cfs_rq))return true; -throttle_cfs_rq (cfs_rq); -return true; +return throttle_cfs_rq (cfs_rq); }static enum hrtimer_restart sched_cfs_slack_timer (struct hrtimer *timer)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 244/388 dpaa2-eth: fix error return code in setup_dpni()
In reply to Greg Kroah-HartmanFrom: Wei Yongjun <[email protected]>
[ Upstream commit 97fff7c8de1e54e5326dfeb66085796864bceb64 ]
Fix to return negative error code -ENOMEM from the error handling case instead of 0, as done elsewhere in this function.
--- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +3 -1
@@ -2654,8 +2654,10 @@ static int setup_dpni(struct fsl_mc_device *ls_dev) priv->cls_rules =devm_kzalloc (dev,sizeof (struct dpaa2_eth_cls_rule ) *dpaa2_eth_fs_count (priv),GFP_KERNEL ); -if (!priv->cls_rules) +if (!priv->cls_rules) { + err = -ENOMEM ; goto close; + }return 0 ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 245/388 dt-bindings: sound: wm8994: Correct required supplies based on actual implementaion
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 8c149b7d75e53be47648742f40fc90d9fc6fa63a ]
The required supplies in bindings were actually not matching implementation making the bindings incorrect and misleading. The Linux kernel driver requires all supplies to be present. Also for wlf,wm8994 uses just DBVDD-supply instead of DBVDDn-supply (n: <1,3>).
--- .../devicetree/bindings/sound/wm8994.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
Documentation/devicetree/bindings/sound/wm8994.txt +12 -6
@@ -14,9 +14,15 @@ Required properties: - #gpio-cells : Must be 2. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). - - AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply, - SPKVDD1-supply, SPKVDD2-supply : power supplies for the device, as covered - in Documentation/devicetree/bindings/regulator/regulator.txt + - power supplies for the device, as covered in + Documentation/devicetree/bindings/regulator/regulator.txt, depending + on compatible: + - for wlf,wm1811 and wlf,wm8958: + AVDD1-supply, AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, + DCVDD-supply, CPVDD-supply, SPKVDD1-supply, SPKVDD2-supply + - for wlf,wm8994: + AVDD1-supply, AVDD2-supply, DBVDD-supply, DCVDD-supply, CPVDD-supply, + SPKVDD1-supply, SPKVDD2-supply Optional properties:
@@ -73,11 +79,11 @@ wm8994: codec@1a { lineout1-se; + AVDD1-supply = <®ulator>; AVDD2-supply = <®ulator>; CPVDD-supply = <®ulator>; - DBVDD1-supply = <®ulator>; - DBVDD2-supply = <®ulator>; - DBVDD3-supply = <®ulator>; + DBVDD-supply = <®ulator>; + DCVDD-supply = <®ulator>; SPKVDD1-supply = <®ulator>; SPKVDD2-supply = <®ulator>; };
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 246/388 devlink: Fix reporters recovery condition
In reply to Greg Kroah-HartmanFrom: Aya Levin <[email protected]>
[ Upstream commit bea0c5c942d3b4e9fb6ed45f6a7de74c6b112437 ]
Devlink health core conditions the reporter's recovery with the expiration of the grace period. This is not relevant for the first recovery. Explicitly demand that the grace period will only apply to recoveries other than the first.
--- net/core/devlink.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
net/core/devlink.c +5 -2
@@ -4823,6 +4823,7 @@ int devlink_health_report(struct devlink_health_reporter *reporter, {enum devlink_health_reporter_state prev_health_state;struct devlink *devlink = reporter->devlink; +unsigned long recover_ts_threshold;/* write a log message of the current error */ WARN_ON (!msg);
@@ -4832,10 +4833,12 @@ int devlink_health_report(struct devlink_health_reporter *reporter, reporter->health_state =DEVLINK_HEALTH_REPORTER_STATE_ERROR ;/* abort if the previous error wasn't recovered */ + recover_ts_threshold = reporter->last_recovery_ts + +msecs_to_jiffies (reporter->graceful_period);if (reporter->auto_recover && (prev_health_state !=DEVLINK_HEALTH_REPORTER_STATE_HEALTHY || - jiffies - reporter->last_recovery_ts < -msecs_to_jiffies (reporter->graceful_period))) { + (reporter->last_recovery_ts && reporter->recovery_count && +time_is_after_jiffies (recover_ts_threshold)))) { trace_devlink_health_recover_aborted(devlink, reporter->ops->name, reporter->health_state,
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 247/388 atm: fix a memory leak of vcc->user_back
In reply to Greg Kroah-HartmanFrom: Cong Wang <[email protected]>
[ Upstream commit 8d9f73c0ad2f20e9fed5380de0a3097825859d03 ]
In lec_arp_clear_vccs() only entry->vcc is freed, but vcc could be installed on entry->recv_vcc too in lec_vcc_added().
This fixes the following memory leak:
unreferenced object 0xffff8880d9266b90 (size 16):
comm "atm2", pid 425, jiffies 4294907980 (age 23.488s) hex dump (first 16 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 6b 6b 6b a5 ............kkk.
backtrace:
[<(____ptrval____)>] kmem_cache_alloc_trace+0x10e/0x151
[<(____ptrval____)>] lane_ioctl+0x4b3/0x569
[<(____ptrval____)>] do_vcc_ioctl+0x1ea/0x236
[<(____ptrval____)>] svc_ioctl+0x17d/0x198
[<(____ptrval____)>] sock_do_ioctl+0x47/0x12f
[<(____ptrval____)>] sock_ioctl+0x2f9/0x322
[<(____ptrval____)>] vfs_ioctl+0x1e/0x2b
[<(____ptrval____)>] ksys_ioctl+0x61/0x80
[<(____ptrval____)>] __x64_sys_ioctl+0x16/0x19
[<(____ptrval____)>] do_syscall_64+0x57/0x65
[<(____ptrval____)>] entry_SYSCALL_64_after_hwframe+0x49/0xb3--- net/atm/lec.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/atm/lec.c +6 -0
@@ -1269,6 +1269,12 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry) entry->vcc =NULL ; }if (entry->recv_vcc) { +struct atm_vcc *vcc = entry->recv_vcc; +struct lec_vcc_priv *vpriv =LEC_VCC_PRIV (vcc); + +kfree (vpriv); + vcc->user_back =NULL ; + entry->recv_vcc->push = entry->old_recv_push;vcc_release_async (entry->recv_vcc, -EPIPE ); entry->recv_vcc =NULL ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 248/388 media: venus: vdec: Init registered list unconditionally
In reply to Greg Kroah-HartmanFrom: Stanimir Varbanov <[email protected]>
[ Upstream commit bc3d870e414b42d72cd386aa20a4fc3612e4feb7 ]
Presently the list initialization is done only in dynamic-resolution-change state, which leads to list corruptions and use-after-free. Init list_head unconditionally in vdec_stop_capture called by vb2 stop_streaming without takeing into account current codec state.
--- drivers/media/platform/qcom/venus/vdec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/media/platform/qcom/venus/vdec.c +3 -2
@@ -987,13 +987,14 @@ static int vdec_stop_capture(struct venus_inst *inst) ret =hfi_session_flush (inst,HFI_FLUSH_OUTPUT );vdec_cancel_dst_buffers (inst); inst->codec_state =VENUS_DEC_STATE_CAPTURE_SETUP ; -INIT_LIST_HEAD (&inst->registeredbufs);venus_helper_free_dpb_bufs (inst);break ;default : -return 0 ; +break ; } +INIT_LIST_HEAD (&inst->registeredbufs); +return ret; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 249/388 perf mem2node: Avoid double free related to realloc
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit 266150c94c69429cf6d18e130237224a047f5061 ]
Realloc of size zero is a free not an error, avoid this causing a double free. Caught by clang's address sanitizer:
==2634==ERROR: AddressSanitizer: attempting double-free on 0x6020000015f0 in thread T0:
#0 0x5649659297fd in free llvm/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:123:3
#1 0x5649659e9251 in __zfree tools/lib/zalloc.c:13:2
#2 0x564965c0f92c in mem2node__exit tools/perf/util/mem2node.c:114:2
#3 0x564965a08b4c in perf_c2c__report tools/perf/builtin-c2c.c:2867:2
#4 0x564965a0616a in cmd_c2c tools/perf/builtin-c2c.c:2989:10
#5 0x564965944348 in run_builtin tools/perf/perf.c:312:11
#6 0x564965943235 in handle_internal_command tools/perf/perf.c:364:8
#7 0x5649659440c4 in run_argv tools/perf/perf.c:408:2
#8 0x564965942e41 in main tools/perf/perf.c:538:30x6020000015f0 is located 0 bytes inside of 1-byte region [0x6020000015f0,0x6020000015f1) freed by thread T0 here:
#0 0x564965929da3 in realloc third_party/llvm/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:164:3
#1 0x564965c0f55e in mem2node__init tools/perf/util/mem2node.c:97:16
#2 0x564965a08956 in perf_c2c__report tools/perf/builtin-c2c.c:2803:8
#3 0x564965a0616a in cmd_c2c tools/perf/builtin-c2c.c:2989:10
#4 0x564965944348 in run_builtin tools/perf/perf.c:312:11
#5 0x564965943235 in handle_internal_command tools/perf/perf.c:364:8
#6 0x5649659440c4 in run_argv tools/perf/perf.c:408:2
#7 0x564965942e41 in main tools/perf/perf.c:538:3previously allocated by thread T0 here:
#0 0x564965929c42 in calloc third_party/llvm/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:154:3
#1 0x5649659e9220 in zalloc tools/lib/zalloc.c:8:9
#2 0x564965c0f32d in mem2node__init tools/perf/util/mem2node.c:61:12
#3 0x564965a08956 in perf_c2c__report tools/perf/builtin-c2c.c:2803:8
#4 0x564965a0616a in cmd_c2c tools/perf/builtin-c2c.c:2989:10
#5 0x564965944348 in run_builtin tools/perf/perf.c:312:11
#6 0x564965943235 in handle_internal_command tools/perf/perf.c:364:8
#7 0x5649659440c4 in run_argv tools/perf/perf.c:408:2
#8 0x564965942e41 in main tools/perf/perf.c:538:3v2: add a WARN_ON_ONCE when the free condition arises.
--- tools/perf/util/mem2node.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/mem2node.c +2 -1
@@ -1,5 +1,6 @@#include <errno.h> #include <inttypes.h> +#include <asm/bug.h> #include <linux/bitmap.h> #include <linux/kernel.h> #include <linux/zalloc.h>
@@ -95,7 +96,7 @@ int mem2node__init(struct mem2node *map, struct perf_env *env)/* Cut unused entries, due to merging. */ tmp_entries =realloc (entries,sizeof (*entries) * j); -if (tmp_entries) +if (tmp_entries ||WARN_ON_ONCE (j ==0 )) entries = tmp_entries;for (i =0 ; i < j; i++) {
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 250/388 mm/slub: fix incorrect interpretation of s->offset
In reply to Greg Kroah-HartmanFrom: Waiman Long <[email protected]>
[ Upstream commit cbfc35a48609ceac978791e3ab9dde0c01f8cb20 ]
In a couple of places in the slub memory allocator, the code uses "s->offset" as a check to see if the free pointer is put right after the object. That check is no longer true with commit 3202fa62fb43 ("slub:
relocate freelist pointer to middle of object").
As a result, echoing "1" into the validate sysfs file, e.g. of dentry, may cause a bunch of "Freepointer corrupt" error reports like the following to appear with the system in panic afterwards.
=============================================================================
BUG dentry(666:pmcd.service) (Tainted: G B): Freepointer corrupt
-----------------------------------------------------------------------------
To fix it, use the check "s->offset == s->inuse" in the new helper function freeptr_outside_object() instead. Also add another helper function get_info_end() to return the end of info block (inuse + free pointer if not overlapping with object).
--- mm/slub.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-)
mm/slub.c +30 -15
@@ -533,15 +533,32 @@ static void print_section(char *level, char *text, u8 *addr,metadata_access_disable (); } +/* +* See comment in calculate_sizes(). +*/ +static inline bool freeptr_outside_object (struct kmem_cache *s) +{ +return s->offset >= s->inuse; +} + +/* +* Return offset of the end of info block which is inuse + free pointer if +* not overlapping with object. +*/ +static inline unsigned int get_info_end (struct kmem_cache *s) +{ +if (freeptr_outside_object (s)) +return s->inuse +sizeof (void *); +else +return s->inuse; +} +static struct track *get_track (struct kmem_cache *s,void *object,enum track_item alloc) {struct track *p; -if (s->offset) - p = object + s->offset +sizeof (void *); -else - p = object + s->inuse; + p = object +get_info_end (s);return p + alloc; }
@@ -682,10 +699,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)print_section (KERN_ERR ,"Redzone " , p + s->object_size, s->inuse - s->object_size); -if (s->offset) - off = s->offset +sizeof (void *); -else - off = s->inuse; + off =get_info_end (s);if (s->flags &SLAB_STORE_USER ) off +=2 *sizeof (struct track );
@@ -776,7 +790,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,* object address * Bytes of the object to be managed. * If the freepointer may overlay the object then the free -* pointer is the first word of the object. +* pointer is at the middle of the object. * * Poisoning uses 0x6b (POISON_FREE) and the last byte is * 0xa5 (POISON_END)
@@ -810,11 +824,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,static int check_pad_bytes (struct kmem_cache *s,struct page *page,u8 *p) { -unsigned long off = s->inuse;/* The end of info */ - -if (s->offset) -/* Freepointer is placed after the object. */ - off +=sizeof (void *); +unsigned long off =get_info_end (s);/* The end of info */ if (s->flags &SLAB_STORE_USER )/* We also have user information there */
@@ -900,7 +910,7 @@ static int check_object(struct kmem_cache *s, struct page *page,check_pad_bytes (s, page, p); } -if (!s->offset && val ==SLUB_RED_ACTIVE ) +if (!freeptr_outside_object (s) && val ==SLUB_RED_ACTIVE )/* * Object and freepointer overlap. Cannot check * freepointer while object is allocated.
@@ -3585,6 +3595,11 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)* * This is the case if we do RCU, have a constructor or * destructor or are poisoning the objects. +* +* The assumption that s->offset >= s->inuse means free +* pointer is outside of the object is used in the +* freeptr_outside_object() function. If that is no +* longer true, the function needs to be modified. */ s->offset = size; size +=sizeof (void *);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 251/388 i2c: tegra: Restore pinmux on system resume
In reply to Greg Kroah-HartmanFrom: Thierry Reding <[email protected]>
[ Upstream commit 44c99904cf61f945d02ac9976ab10dd5ccaea393 ]
Depending on the board design, the I2C controllers found on Tegra SoCs may require pinmuxing in order to function. This is done as part of the driver's runtime suspend/resume operations. However, the PM core does not allow devices to go into runtime suspend during system sleep to avoid potential races with the suspend/resume of their parents.
As a result of this, when Tegra SoCs resume from system suspend, their I2C controllers may have lost the pinmux state in hardware, whereas the pinctrl subsystem is not aware of this. To fix this, make sure that if the I2C controller is not runtime suspended, the runtime suspend code is still executed in order to disable the module clock (which we don't need to be enabled during sleep) and set the pinmux to the idle state.
Conversely, make sure that the I2C controller is properly resumed when waking up from sleep so that pinmux settings are properly restored.
This fixes a bug seen with DDC transactions to an HDMI monitor timing out when resuming from system suspend.
--- drivers/i2c/busses/i2c-tegra.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-)
drivers/i2c/busses/i2c-tegra.c +19 -4
@@ -1721,10 +1721,14 @@ static int tegra_i2c_remove(struct platform_device *pdev)static int __maybe_unused tegra_i2c_suspend (struct device *dev) {struct tegra_i2c_dev *i2c_dev =dev_get_drvdata (dev); +int err =0 ;i2c_mark_adapter_suspended (&i2c_dev->adapter); -return 0 ; +if (!pm_runtime_status_suspended (dev)) + err =tegra_i2c_runtime_suspend (dev); + +return err; }static int __maybe_unused tegra_i2c_resume (struct device *dev)
@@ -1732,6 +1736,10 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)struct tegra_i2c_dev *i2c_dev =dev_get_drvdata (dev);int err; +/* +* We need to ensure that clocks are enabled so that registers can be +* restored in tegra_i2c_init(). +*/ err =tegra_i2c_runtime_resume (dev);if (err)return err;
@@ -1740,9 +1748,16 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)if (err)return err; - err =tegra_i2c_runtime_suspend (dev); -if (err) -return err; +/* +* In case we are runtime suspended, disable clocks again so that we +* don't unbalance the clock reference counts during the next runtime +* resume transition. +*/ +if (pm_runtime_status_suspended (dev)) { + err =tegra_i2c_runtime_suspend (dev); +if (err) +return err; + }i2c_mark_adapter_resumed (&i2c_dev->adapter);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 252/388 power: supply: max17040: Correct voltage reading
In reply to Greg Kroah-HartmanFrom: Jonathan Bakker <[email protected]>
[ Upstream commit 0383024f811aa469df258039807810fc3793a105 ]
According to the datasheet available at (1), the bottom four bits are always zero and the actual voltage is 1.25x this value in mV. Since the kernel API specifies that voltages should be in uV, it should report 1250x the shifted value.
1) https://datasheets.maximintegrated.com/en/ds/MAX17040-MAX17041.pdf
--- drivers/power/supply/max17040_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/max17040_battery.c +1 -1
@@ -105,7 +105,7 @@ static void max17040_get_vcell(struct i2c_client *client) vcell =max17040_read_reg (client,MAX17040_VCELL ); - chip->vcell = vcell; + chip->vcell = (vcell >>4 ) *1250 ; }static void max17040_get_soc (struct i2c_client *client)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 253/388 phy: samsung: s5pv210-usb2: Add delay after reset
In reply to Greg Kroah-HartmanFrom: Jonathan Bakker <[email protected]>
[ Upstream commit 05942b8c36c7eb5d3fc5e375d4b0d0c49562e85d ]
The USB phy takes some time to reset, so make sure we give it to it. The delay length was taken from the 4x12 phy driver.
This manifested in issues with the DWC2 driver since commit fe369e1826b3 ("usb: dwc2: Make dwc2_readl/writel functions endianness-agnostic.") where the endianness check would read the DWC ID as 0 due to the phy still resetting, resulting in the wrong endian mode being chosen.
--- drivers/phy/samsung/phy-s5pv210-usb2.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/phy/samsung/phy-s5pv210-usb2.c +4 -0
@@ -139,6 +139,10 @@ static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)udelay (10 ); rst &= ~rstbits;writel (rst, drv->reg_phy +S5PV210_UPHYRST ); +/* The following delay is necessary for the reset sequence to be +* completed +*/ +udelay (80 ); }else { pwr =readl (drv->reg_phy +S5PV210_UPHYPWR ); pwr |= phypwr;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 254/388 Bluetooth: Handle Inquiry Cancel error after Inquiry Complete
In reply to Greg Kroah-HartmanFrom: Sonny Sasaka <[email protected]>
[ Upstream commit adf1d6926444029396861413aba8a0f2a805742a ]
After sending Inquiry Cancel command to the controller, it is possible that Inquiry Complete event comes before Inquiry Cancel command complete event. In this case the Inquiry Cancel command will have status of Command Disallowed since there is no Inquiry session to be cancelled. This case should not be treated as error, otherwise we can reach an inconsistent state.
Example of a btmon trace when this happened:
< HCI Command: Inquiry Cancel (0x01|0x0002) plen 0
Quoted 1 line
HCI Event: Inquiry Complete (
0x01) plen 1
Status: Success (0x00)
Quoted 1 line
HCI Event: Command Complete (
0x0e) plen 4
Inquiry Cancel (0x01|0x0002) ncmd 1
Status: Command Disallowed (0x0c)--- net/bluetooth/hci_event.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
net/bluetooth/hci_event.c +17 -2
@@ -41,12 +41,27 @@/* Handle HCI Event packets */ -static void hci_cc_inquiry_cancel (struct hci_dev *hdev,struct sk_buff *skb) +static void hci_cc_inquiry_cancel (struct hci_dev *hdev,struct sk_buff *skb, +u8 *new_status) {__u8 status = *((__u8 *) skb->data);BT_DBG ("%s status 0x%2.2x" , hdev->name, status); +/* It is possible that we receive Inquiry Complete event right +* before we receive Inquiry Cancel Command Complete event, in +* which case the latter event should have status of Command +* Disallowed (0x0c). This should not be treated as error, since +* we actually achieve what Inquiry Cancel wants to achieve, +* which is to end the last Inquiry session. +*/ +if (status ==0x0c && !test_bit (HCI_INQUIRY , &hdev->flags)) { +bt_dev_warn (hdev,"Ignoring error of Inquiry Cancel command" ); + status =0x00 ; + } + + *new_status = status; +if (status)return ;
@@ -3142,7 +3157,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,switch (*opcode) {case HCI_OP_INQUIRY_CANCEL : -hci_cc_inquiry_cancel (hdev, skb); +hci_cc_inquiry_cancel (hdev, skb, status);break ;case HCI_OP_PERIODIC_INQ :
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 255/388 USB: EHCI: ehci-mv: fix error handling in mv_ehci_probe()
In reply to Greg Kroah-HartmanFrom: Tang Bin <[email protected]>
[ Upstream commit c856b4b0fdb5044bca4c0acf9a66f3b5cc01a37a ]
If the function platform_get_irq() failed, the negative value returned will not be detected here. So fix error handling in mv_ehci_probe(). And when get irq failed, the function platform_get_irq() logs an error message, so remove redundant message here.
--- drivers/usb/host/ehci-mv.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/host/ehci-mv.c +2 -3
@@ -157,9 +157,8 @@ static int mv_ehci_probe(struct platform_device *pdev) hcd->regs = ehci_mv->op_regs; hcd->irq =platform_get_irq (pdev,0 ); -if (!hcd->irq) { -dev_err (&pdev->dev,"Cannot get irq." ); - retval = -ENODEV ; +if (hcd->irq <0 ) { + retval = hcd->irq; goto err_disable_clk; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 256/388 KVM: x86: handle wrap around 32-bit address space
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
[ Upstream commit fede8076aab4c2280c673492f8f7a2e87712e8b4 ]
KVM is not handling the case where EIP wraps around the 32-bit address space (that is, outside long mode). This is needed both in vmx.c and in emulate.c. SVM with NRIPS is okay, but it can still print an error to dmesg due to integer overflow.
--- arch/x86/kvm/emulate.c | 2 ++ arch/x86/kvm/svm.c | 3 --- arch/x86/kvm/vmx/vmx.c | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-)
arch/x86/kvm/emulate.c +2 -0
@@ -5836,6 +5836,8 @@ writeback: } ctxt->eip = ctxt->_eip; +if (ctxt->mode !=X86EMUL_MODE_PROT64 ) + ctxt->eip = (u32 )ctxt->_eip; done:if (rc ==X86EMUL_PROPAGATE_FAULT ) {
arch/x86/kvm/svm.c +0 -3
@@ -787,9 +787,6 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)if (!kvm_emulate_instruction (vcpu,EMULTYPE_SKIP ))return 0 ; }else { -if (svm->next_rip -kvm_rip_read (vcpu) >MAX_INST_SIZE ) -pr_err ("%s: ip 0x%lx next 0x%llx\n" , - __func__,kvm_rip_read (vcpu), svm->next_rip);kvm_rip_write (vcpu, svm->next_rip); }svm_set_interrupt_shadow (vcpu,0 );
arch/x86/kvm/vmx/vmx.c +12 -3
@@ -1541,7 +1541,7 @@ static int vmx_rtit_ctl_check(struct kvm_vcpu *vcpu, u64 data)static int skip_emulated_instruction (struct kvm_vcpu *vcpu) { -unsigned long rip; +unsigned long rip, orig_rip;/* * Using VMCS.VM_EXIT_INSTRUCTION_LEN on EPT misconfig depends on
@@ -1553,8 +1553,17 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)*/ if (!static_cpu_has (X86_FEATURE_HYPERVISOR ) ||to_vmx (vcpu)->exit_reason !=EXIT_REASON_EPT_MISCONFIG ) { - rip =kvm_rip_read (vcpu); - rip +=vmcs_read32 (VM_EXIT_INSTRUCTION_LEN ); + orig_rip =kvm_rip_read (vcpu); + rip = orig_rip +vmcs_read32 (VM_EXIT_INSTRUCTION_LEN ); +#ifdef CONFIG_X86_64 +/* +* We need to mask out the high 32 bits of RIP if not in 64-bit +* mode, but just finding out that we are in 64-bit mode is +* quite expensive. Only do it if there was a carry. +*/ +if (unlikely (((rip ^ orig_rip) >>31 ) ==3 ) && !is_64_bit_mode (vcpu)) + rip = (u32 )rip; +#endif kvm_rip_write (vcpu, rip); }else {if (!kvm_emulate_instruction (vcpu,EMULTYPE_SKIP ))
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 257/388 tipc: fix memory leak in service subscripting
In reply to Greg Kroah-HartmanFrom: Tuong Lien <[email protected]>
[ Upstream commit 0771d7df819284d46cf5cfb57698621b503ec17f ]
Upon receipt of a service subscription request from user via a topology connection, one 'sub' object will be allocated in kernel, so it will be able to send an event of the service if any to the user correspondingly then. Also, in case of any failure, the connection will be shutdown and all the pertaining 'sub' objects will be freed.
However, there is a race condition as follows resulting in memory leak:
receive-work connection send-work
| | |
sub-1 |<------//-------| |
sub-2 |<------//-------| |
| |<---------------| evt for sub-x
sub-3 |<------//-------| |
: : :
: : :
| /--------| |
| | * peer closed |
| | | |
| | |<-------X-------| evt for sub-y
| | |<===============|
sub-n |<------/ X shutdown |
-> orphan | |That is, the 'receive-work' may get the last subscription request while the 'send-work' is shutting down the connection due to peer close.
We had a 'lock' on the connection, so the two actions cannot be carried out simultaneously. If the last subscription is allocated e.g. 'sub-n', before the 'send-work' closes the connection, there will be no issue at all, the 'sub' objects will be freed. In contrast the last subscription will become orphan since the connection was closed, and we released all references.
This commit fixes the issue by simply adding one test if the connection remains in 'connected' state right after we obtain the connection lock, then a subscription object can be created as usual, otherwise we ignore it.
--- net/tipc/topsrv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/tipc/topsrv.c +3 -1
@@ -400,7 +400,9 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con)return -EWOULDBLOCK ;if (ret ==sizeof (s)) {read_lock_bh (&sk->sk_callback_lock); - ret =tipc_conn_rcv_sub (srv, con, &s); +/* RACE: the connection can be closed in the meantime */ +if (likely (connected (con))) + ret =tipc_conn_rcv_sub (srv, con, &s);read_unlock_bh (&sk->sk_callback_lock);if (!ret)return 0 ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 258/388 tty: serial: samsung: Correct clock selection logic
In reply to Greg Kroah-HartmanFrom: Jonathan Bakker <[email protected]>
[ Upstream commit 7d31676a8d91dd18e08853efd1cb26961a38c6a6 ]
Some variants of the samsung tty driver can pick which clock to use for their baud rate generation. In the DT conversion, a default clock was selected to be used if a specific one wasn't assigned and then a comparison of which clock rate worked better was done. Unfortunately, the comparison was implemented in such a way that only the default clock was ever actually compared. Fix this by iterating through all possible clocks, except when a specific clock has already been picked via clk_sel (which is only possible via board files).
--- drivers/tty/serial/samsung.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/tty/serial/samsung.c +4 -4
@@ -1187,14 +1187,14 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,struct s3c24xx_uart_info *info = ourport->info;struct clk *clk;unsigned long rate; -unsigned int cnt, baud, quot, clk_sel, best_quot =0 ; +unsigned int cnt, baud, quot, best_quot =0 ;char clkname[MAX_CLK_NAME_LENGTH ];int calc_deviation, deviation = (1 <<30 ) -1 ; - clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel : - ourport->info->def_clk_sel;for (cnt =0 ; cnt < info->num_clks; cnt++) { -if (!(clk_sel & (1 << cnt))) +/* Keep selected clock if provided */ +if (ourport->cfg->clk_sel && + !(ourport->cfg->clk_sel & (1 << cnt)))continue ;sprintf (clkname,"clk_uart_baud%d" , cnt);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 259/388 ALSA: hda: Fix potential race in unsol event handler
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
[ Upstream commit c637fa151259c0f74665fde7cba5b7eac1417ae5 ]
The unsol event handling code has a loop retrieving the read/write indices and the arrays without locking while the append to the array may happen concurrently. This may lead to some inconsistency. Although there hasn't been any proof of this bad results, it's still safer to protect the racy accesses.
This patch adds the spinlock protection around the unsol handling loop for addressing it. Here we take bus->reg_lock as the writer side snd_hdac_bus_queue_event() is also protected by that lock.
--- sound/hda/hdac_bus.c | 4 ++++ 1 file changed, 4 insertions(+)
sound/hda/hdac_bus.c +4 -0
@@ -158,6 +158,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work)struct hdac_driver *drv;unsigned int rp, caddr, res; +spin_lock_irq (&bus->reg_lock);while (bus->unsol_rp != bus->unsol_wp) { rp = (bus->unsol_rp +1 ) %HDA_UNSOL_QUEUE_SIZE ; bus->unsol_rp = rp;
@@ -169,10 +170,13 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work) codec = bus->caddr_tbl[caddr &0x0f ];if (!codec || !codec->dev.driver)continue ; +spin_unlock_irq (&bus->reg_lock); drv =drv_to_hdac_driver (codec->dev.driver);if (drv->unsol_event) drv->unsol_event (codec, res); +spin_lock_irq (&bus->reg_lock); } +spin_unlock_irq (&bus->reg_lock); }/**
Signature · 1 line
2.25.1