]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.3/powerpc-perf-hv-24x7-use-per-cpu-page-buffer.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 3.18.3 / powerpc-perf-hv-24x7-use-per-cpu-page-buffer.patch
1 From f34b6c72c3ebaa286d3311a825ef79eccbcca82f Mon Sep 17 00:00:00 2001
2 From: "sukadev@linux.vnet.ibm.com" <sukadev@linux.vnet.ibm.com>
3 Date: Wed, 10 Dec 2014 14:29:13 -0800
4 Subject: powerpc/perf/hv-24x7: Use per-cpu page buffer
5
6 From: "sukadev@linux.vnet.ibm.com" <sukadev@linux.vnet.ibm.com>
7
8 commit f34b6c72c3ebaa286d3311a825ef79eccbcca82f upstream.
9
10 The 24x7 counters are continuously running and not updated on an
11 interrupt. So we record the event counts when stopping the event or
12 deleting it.
13
14 But to "read" a single counter in 24x7, we allocate a page and pass it
15 into the hypervisor (The HV returns the page full of counters from which
16 we extract the specific counter for this event).
17
18 We allocate a page using GFP_USER and when deleting the event, we end up
19 with the following warning because we are blocking in interrupt context.
20
21 [ 698.641709] BUG: scheduling while atomic: swapper/0/0/0x10010000
22
23 We could use GFP_ATOMIC but that could result in failures. Pre-allocate
24 a buffer so we don't have to allocate in interrupt context. Further as
25 Michael Ellerman suggested, use Per-CPU buffer so we only need to
26 allocate once per CPU.
27
28 Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
29 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
30 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31
32 ---
33 arch/powerpc/perf/hv-24x7.c | 21 +++++++++------------
34 1 file changed, 9 insertions(+), 12 deletions(-)
35
36 --- a/arch/powerpc/perf/hv-24x7.c
37 +++ b/arch/powerpc/perf/hv-24x7.c
38 @@ -217,11 +217,14 @@ static bool is_physical_domain(int domai
39 domain == HV_24X7_PERF_DOMAIN_PHYSICAL_CORE;
40 }
41
42 +DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096);
43 +DEFINE_PER_CPU(char, hv_24x7_resb[4096]) __aligned(4096);
44 +
45 static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix,
46 u16 lpar, u64 *res,
47 bool success_expected)
48 {
49 - unsigned long ret = -ENOMEM;
50 + unsigned long ret;
51
52 /*
53 * request_buffer and result_buffer are not required to be 4k aligned,
54 @@ -243,13 +246,11 @@ static unsigned long single_24x7_request
55 BUILD_BUG_ON(sizeof(*request_buffer) > 4096);
56 BUILD_BUG_ON(sizeof(*result_buffer) > 4096);
57
58 - request_buffer = kmem_cache_zalloc(hv_page_cache, GFP_USER);
59 - if (!request_buffer)
60 - goto out;
61 + request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
62 + result_buffer = (void *)get_cpu_var(hv_24x7_resb);
63
64 - result_buffer = kmem_cache_zalloc(hv_page_cache, GFP_USER);
65 - if (!result_buffer)
66 - goto out_free_request_buffer;
67 + memset(request_buffer, 0, 4096);
68 + memset(result_buffer, 0, 4096);
69
70 *request_buffer = (struct reqb) {
71 .buf = {
72 @@ -278,15 +279,11 @@ static unsigned long single_24x7_request
73 domain, offset, ix, lpar, ret, ret,
74 result_buffer->buf.detailed_rc,
75 result_buffer->buf.failing_request_ix);
76 - goto out_free_result_buffer;
77 + goto out;
78 }
79
80 *res = be64_to_cpu(result_buffer->result);
81
82 -out_free_result_buffer:
83 - kfree(result_buffer);
84 -out_free_request_buffer:
85 - kfree(request_buffer);
86 out:
87 return ret;
88 }