lkml.org 
[lkml]   [2015]   [Jul]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:x86/apic] x86/apic: Migrate apic timer to new set_state interface
    Commit-ID:  b23d8e527815954768861bb20d2b224009fff7cd
    Gitweb: http://git.kernel.org/tip/b23d8e527815954768861bb20d2b224009fff7cd
    Author: Viresh Kumar <viresh.kumar@linaro.org>
    AuthorDate: Thu, 16 Jul 2015 16:28:44 +0530
    Committer: Thomas Gleixner <tglx@linutronix.de>
    CommitDate: Thu, 30 Jul 2015 00:51:47 +0200

    x86/apic: Migrate apic timer to new set_state interface

    Migrate apic driver to the new 'set-state' interface provided by
    clockevents core, the earlier 'set-mode' interface is marked obsolete
    now.

    This also enables us to implement callbacks for new states of clockevent
    devices, for example: ONESHOT_STOPPED.

    We weren't doing anything while switching to resume mode and so that
    callback isn't implemented.

    Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
    Cc: linaro-kernel@lists.linaro.org
    Cc: Jiang Liu <jiang.liu@linux.intel.com>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: David Rientjes <rientjes@google.com>
    Cc: Bandan Das <bsd@redhat.com>
    Link: http://lkml.kernel.org/r/1896ac5989d27f2ac37f4786af9bd537e1921b83.1437042675.git.viresh.kumar@linaro.org
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    ---
    arch/x86/kernel/apic/apic.c | 86 +++++++++++++++++++++++++++------------------
    1 file changed, 51 insertions(+), 35 deletions(-)

    diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
    index dcb5285..ecd6705 100644
    --- a/arch/x86/kernel/apic/apic.c
    +++ b/arch/x86/kernel/apic/apic.c
    @@ -462,40 +462,53 @@ static int lapic_next_deadline(unsigned long delta,
    return 0;
    }

    -/*
    - * Setup the lapic timer in periodic or oneshot mode
    - */
    -static void lapic_timer_setup(enum clock_event_mode mode,
    - struct clock_event_device *evt)
    +static int lapic_timer_shutdown(struct clock_event_device *evt)
    {
    unsigned long flags;
    unsigned int v;

    /* Lapic used as dummy for broadcast ? */
    if (evt->features & CLOCK_EVT_FEAT_DUMMY)
    - return;
    + return 0;

    local_irq_save(flags);

    - switch (mode) {
    - case CLOCK_EVT_MODE_PERIODIC:
    - case CLOCK_EVT_MODE_ONESHOT:
    - __setup_APIC_LVTT(lapic_timer_frequency,
    - mode != CLOCK_EVT_MODE_PERIODIC, 1);
    - break;
    - case CLOCK_EVT_MODE_UNUSED:
    - case CLOCK_EVT_MODE_SHUTDOWN:
    - v = apic_read(APIC_LVTT);
    - v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
    - apic_write(APIC_LVTT, v);
    - apic_write(APIC_TMICT, 0);
    - break;
    - case CLOCK_EVT_MODE_RESUME:
    - /* Nothing to do here */
    - break;
    - }
    + v = apic_read(APIC_LVTT);
    + v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
    + apic_write(APIC_LVTT, v);
    + apic_write(APIC_TMICT, 0);
    +
    + local_irq_restore(flags);
    +
    + return 0;
    +}
    +
    +static inline int
    +lapic_timer_set_periodic_oneshot(struct clock_event_device *evt, bool oneshot)
    +{
    + unsigned long flags;
    +
    + /* Lapic used as dummy for broadcast ? */
    + if (evt->features & CLOCK_EVT_FEAT_DUMMY)
    + return 0;
    +
    + local_irq_save(flags);
    +
    + __setup_APIC_LVTT(lapic_timer_frequency, oneshot, 1);

    local_irq_restore(flags);
    +
    + return 0;
    +}
    +
    +static int lapic_timer_set_periodic(struct clock_event_device *evt)
    +{
    + return lapic_timer_set_periodic_oneshot(evt, false);
    +}
    +
    +static int lapic_timer_set_oneshot(struct clock_event_device *evt)
    +{
    + return lapic_timer_set_periodic_oneshot(evt, true);
    }

    /*
    @@ -513,15 +526,18 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
    * The local apic timer can be used for any function which is CPU local.
    */
    static struct clock_event_device lapic_clockevent = {
    - .name = "lapic",
    - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
    - | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
    - .shift = 32,
    - .set_mode = lapic_timer_setup,
    - .set_next_event = lapic_next_event,
    - .broadcast = lapic_timer_broadcast,
    - .rating = 100,
    - .irq = -1,
    + .name = "lapic",
    + .features = CLOCK_EVT_FEAT_PERIODIC |
    + CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP
    + | CLOCK_EVT_FEAT_DUMMY,
    + .shift = 32,
    + .set_state_shutdown = lapic_timer_shutdown,
    + .set_state_periodic = lapic_timer_set_periodic,
    + .set_state_oneshot = lapic_timer_set_oneshot,
    + .set_next_event = lapic_next_event,
    + .broadcast = lapic_timer_broadcast,
    + .rating = 100,
    + .irq = -1,
    };
    static DEFINE_PER_CPU(struct clock_event_device, lapic_events);

    @@ -778,7 +794,7 @@ static int __init calibrate_APIC_clock(void)
    * Setup the apic timer manually
    */
    levt->event_handler = lapic_cal_handler;
    - lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
    + lapic_timer_set_periodic(levt);
    lapic_cal_loops = -1;

    /* Let the interrupts run */
    @@ -788,7 +804,7 @@ static int __init calibrate_APIC_clock(void)
    cpu_relax();

    /* Stop the lapic timer */
    - lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
    + lapic_timer_shutdown(levt);

    /* Jiffies delta */
    deltaj = lapic_cal_j2 - lapic_cal_j1;
    @@ -878,7 +894,7 @@ static void local_apic_timer_interrupt(void)
    if (!evt->event_handler) {
    pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu);
    /* Switch it off */
    - lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
    + lapic_timer_shutdown(evt);
    return;
    }


    \
     
     \ /
      Last update: 2015-07-30 21:41    [W:5.042 / U:0.100 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site