lkml.org 
[lkml]   [2020]   [Nov]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 174/214] ARC: perf: redo the pct irq missing in device-tree handling
    Date
    From: Vineet Gupta <vgupta@synopsys.com>

    commit 8c42a5c02bec6c7eccf08957be3c6c8fccf9790b upstream.

    commit feb92d7d3813456c11dce21 "(ARC: perf: don't bail setup if pct irq
    missing in device-tree)" introduced a silly brown-paper bag bug:
    The assignment and comparison in an if statement were not bracketed
    correctly leaving the order of evaluation undefined.

    |
    | if (has_interrupts && (irq = platform_get_irq(pdev, 0) >= 0)) {
    | ^^^ ^^^^

    And given such a chance, the compiler will bite you hard, fully entitled
    to generating this piece of beauty:

    |
    | # if (has_interrupts && (irq = platform_get_irq(pdev, 0) >= 0)) {
    |
    | bl.d @platform_get_irq <-- irq returned in r0
    |
    | setge r2, r0, 0 <-- r2 is bool 1 or 0 if irq >= 0 true/false
    | brlt.d r0, 0, @.L114
    |
    | st_s r2,[sp] <-- irq saved is bool 1 or 0, not actual return val
    | st 1,[r3,160] # arc_pmu.18_29->irq <-- drops bool and assumes 1
    |
    | # return __request_percpu_irq(irq, handler, 0,
    |
    | bl.d @__request_percpu_irq;
    | mov_s r0,1 <-- drops even bool and assumes 1 which fails

    With the snafu fixed, everything is as expected.

    | bl.d @platform_get_irq <-- returns irq in r0
    |
    | mov_s r2,r0
    | brlt.d r2, 0, @.L112
    |
    | st_s r0,[sp] <-- irq isaved is actual return value above
    | st r0,[r13,160] #arc_pmu.18_27->irq
    |
    | bl.d @__request_percpu_irq <-- r0 unchanged so actual irq returned
    | add r4,r4,r12 #, tmp363, __ptr

    Cc: <stable@vger.kernel.org>
    Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/arc/kernel/perf_event.c | 29 +++++++++++++++++++----------
    1 file changed, 19 insertions(+), 10 deletions(-)

    --- a/arch/arc/kernel/perf_event.c
    +++ b/arch/arc/kernel/perf_event.c
    @@ -562,7 +562,7 @@ static int arc_pmu_device_probe(struct p
    {
    struct arc_reg_pct_build pct_bcr;
    struct arc_reg_cc_build cc_bcr;
    - int i, has_interrupts, irq;
    + int i, has_interrupts, irq = -1;
    int counter_size; /* in bits */

    union cc_name {
    @@ -637,18 +637,27 @@ static int arc_pmu_device_probe(struct p
    .attr_groups = arc_pmu->attr_groups,
    };

    - if (has_interrupts && (irq = platform_get_irq(pdev, 0) >= 0)) {
    + if (has_interrupts) {
    + irq = platform_get_irq(pdev, 0);
    + if (irq >= 0) {
    + int ret;
    +
    + arc_pmu->irq = irq;
    +
    + /* intc map function ensures irq_set_percpu_devid() called */
    + ret = request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
    + this_cpu_ptr(&arc_pmu_cpu));
    +
    + if (!ret)
    + on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
    + else
    + irq = -1;
    + }

    - arc_pmu->irq = irq;
    -
    - /* intc map function ensures irq_set_percpu_devid() called */
    - request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
    - this_cpu_ptr(&arc_pmu_cpu));
    + }

    - on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
    - } else {
    + if (irq == -1)
    arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
    - }

    /*
    * perf parser doesn't really like '-' symbol in events name, so let's

    \
     
     \ /
      Last update: 2020-11-03 21:59    [W:2.076 / U:1.128 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site