diff options
author | Anton Blanchard <anton@samba.org> | 2013-11-17 11:39:05 +1100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-09 10:51:22 -0700 |
commit | 9e1ba6fccd86b50c3d893e5128515f355df6b066 (patch) | |
tree | 026ff5068425bbfffe4da7c4af64024923189128 /arch | |
parent | a1ca0f8ee2e5874e309f2a9956e74edfdf541ce4 (diff) |
powerpc/pseries: Duplicate dtl entries sometimes sent to userspace
commit 84b073868b9d9e754ae48b828337633d1b386482 upstream.
When reading from the dispatch trace log (dtl) userspace interface, I
sometimes see duplicate entries. One example:
# hexdump -C dtl.out
00000000 07 04 00 0c 00 00 48 44 00 00 00 00 00 00 00 00
00000010 00 0c a0 b4 16 83 6d 68 00 00 00 00 00 00 00 00
00000020 00 00 00 00 10 00 13 50 80 00 00 00 00 00 d0 32
00000030 07 04 00 0c 00 00 48 44 00 00 00 00 00 00 00 00
00000040 00 0c a0 b4 16 83 6d 68 00 00 00 00 00 00 00 00
00000050 00 00 00 00 10 00 13 50 80 00 00 00 00 00 d0 32
The problem is in scan_dispatch_log() where we call dtl_consumer()
but bail out before incrementing the index.
To fix this I moved dtl_consumer() after the timebase comparison.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/time.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index eb6b72faec0..b32729b694c 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -212,8 +212,6 @@ static u64 scan_dispatch_log(u64 stop_tb) if (i == vpa->dtl_idx) return 0; while (i < vpa->dtl_idx) { - if (dtl_consumer) - dtl_consumer(dtl, i); dtb = dtl->timebase; tb_delta = dtl->enqueue_to_dispatch_time + dtl->ready_to_enqueue_time; @@ -226,6 +224,8 @@ static u64 scan_dispatch_log(u64 stop_tb) } if (dtb > stop_tb) break; + if (dtl_consumer) + dtl_consumer(dtl, i); stolen += tb_delta; ++i; ++dtl; |