WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86/HPET: cleanup

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86/HPET: cleanup
From: Xen patchbot-unstable <patchbot@xxxxxxx>
Date: Sun, 20 Mar 2011 06:40:09 +0000
Delivery-date: Sat, 19 Mar 2011 23:40:51 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxxxx>
# Date 1299935974 0
# Node ID 5263151fba9b6e69f65180839cd51b03de8ac560
# Parent  87aa1277eae02fbafab3da4276fb9f9c7a8bdf26
x86/HPET: cleanup

- separate init and resume code paths (so that the [larger] init parts
  can go init .init.* sections)
- drop the separate legacy_hpet_event object, as we can easily re-use
  the first slot of hpet_events[] for that purpose (the whole array is
  otherwise unused when the legacy code is being used)
- use section placement attributes where reasonable

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Acked-by: Wei Gang <gang.wei@xxxxxxxxx>
---


diff -r 87aa1277eae0 -r 5263151fba9b xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c       Sat Mar 12 13:19:02 2011 +0000
+++ b/xen/arch/x86/hpet.c       Sat Mar 12 13:19:34 2011 +0000
@@ -27,6 +27,8 @@
 #define HPET_EVT_USED       (1 << HPET_EVT_USED_BIT)
 #define HPET_EVT_DISABLE_BIT 1
 #define HPET_EVT_DISABLE    (1 << HPET_EVT_DISABLE_BIT)
+#define HPET_EVT_LEGACY_BIT  2
+#define HPET_EVT_LEGACY     (1 << HPET_EVT_LEGACY_BIT)
 
 struct hpet_event_channel
 {
@@ -54,18 +56,18 @@
     int irq;            /* msi irq */
     unsigned int flags; /* HPET_EVT_x */
 } __cacheline_aligned;
-static struct hpet_event_channel legacy_hpet_event;
 static struct hpet_event_channel hpet_events[MAX_HPET_NUM] = 
     { [0 ... MAX_HPET_NUM-1].irq = -1 };
-static unsigned int num_hpets_used; /* msi hpet channels used for broadcast */
+
+/* msi hpet channels used for broadcast */
+static unsigned int __read_mostly num_hpets_used;
 
 DEFINE_PER_CPU(struct hpet_event_channel *, cpu_bc_channel);
 
-static int *irq_channel;
-
+static int *__read_mostly irq_channel;
 #define irq_to_channel(irq)   irq_channel[irq]
 
-unsigned long hpet_address;
+unsigned long __read_mostly hpet_address;
 
 /*
  * force_hpet_broadcast: by default legacy hpet broadcast will be stopped
@@ -362,58 +364,50 @@
     .set_affinity   = hpet_msi_set_affinity,
 };
 
-static int hpet_setup_msi_irq(unsigned int irq)
+static void __hpet_setup_msi_irq(unsigned int irq)
 {
-    int ret;
     struct msi_msg msg;
-    struct hpet_event_channel *ch = &hpet_events[irq_to_channel(irq)];
-    irq_desc_t *desc = irq_to_desc(irq);
-
-    if ( desc->handler == &no_irq_type )
-    {
-        desc->handler = &hpet_msi_type;
-        ret = request_irq(irq, hpet_interrupt_handler,
-                          0, "HPET", ch);
-        if ( ret < 0 )
-            return ret;
-    }
-    else if ( desc->handler != &hpet_msi_type )
-    {
-        return -EINVAL;
-    }
 
     msi_compose_msg(NULL, irq, &msg);
     hpet_msi_write(irq, &msg);
+}
+
+static int __init hpet_setup_msi_irq(unsigned int irq)
+{
+    int ret;
+    irq_desc_t *desc = irq_to_desc(irq);
+
+    desc->handler = &hpet_msi_type;
+    ret = request_irq(irq, hpet_interrupt_handler,
+                      0, "HPET", hpet_events + irq_channel[irq]);
+    if ( ret < 0 )
+        return ret;
+
+    __hpet_setup_msi_irq(irq);
 
     return 0;
 }
 
-static int hpet_assign_irq(struct hpet_event_channel *ch)
+static int __init hpet_assign_irq(unsigned int idx)
 {
-    int irq = ch->irq;
+    int irq;
 
-    if ( irq < 0 )
-    {
-        if ( (irq = create_irq()) < 0 )
-            return irq;
+    if ( (irq = create_irq()) < 0 )
+        return irq;
 
-        irq_channel[irq] = ch - &hpet_events[0];
-        ch->irq = irq;
-    }
+    irq_channel[irq] = idx;
 
-    /* hpet_setup_msi_irq should also be called for S3 resuming */
     if ( hpet_setup_msi_irq(irq) )
     {
         destroy_irq(irq);
         irq_channel[irq] = -1;
-        ch->irq = -1;
         return -EINVAL;
     }
 
-    return 0;
+    return irq;
 }
 
-static int hpet_fsb_cap_lookup(void)
+static int __init hpet_fsb_cap_lookup(void)
 {
     unsigned int id;
     unsigned int num_chs, num_chs_used;
@@ -445,7 +439,7 @@
         ch->flags = 0;
         ch->idx = i;
 
-        if ( hpet_assign_irq(ch) )
+        if ( (ch->irq = hpet_assign_irq(num_chs_used)) < 0 )
             continue;
 
         num_chs_used++;
@@ -468,7 +462,7 @@
     struct hpet_event_channel *ch;
 
     if ( num_hpets_used == 0 )
-        return &legacy_hpet_event;
+        return hpet_events;
 
     spin_lock(&next_lock);
     next = next_channel = (next_channel + 1) % num_hpets_used;
@@ -536,7 +530,7 @@
 
 #include <asm/mc146818rtc.h>
 
-void (*pv_rtc_handler)(unsigned int port, uint8_t value);
+void (*__read_mostly pv_rtc_handler)(unsigned int port, uint8_t value);
 
 static void handle_rtc_once(unsigned int port, uint8_t value)
 {
@@ -559,87 +553,114 @@
     }
 }
 
-void hpet_broadcast_init(void)
+void __init hpet_broadcast_init(void)
 {
-    u64 hpet_rate;
+    u64 hpet_rate = hpet_setup();
     u32 hpet_id, cfg;
-    int i;
+    unsigned int i, n;
 
-    if ( irq_channel == NULL )
-    {
-        irq_channel = xmalloc_array(int, nr_irqs);
-        BUG_ON(irq_channel == NULL);
-        for ( i = 0; i < nr_irqs; i++ )
-            irq_channel[i] = -1;
-    }
-
-    hpet_rate = hpet_setup();
     if ( hpet_rate == 0 )
         return;
 
+    irq_channel = xmalloc_array(int, nr_irqs);
+    BUG_ON(irq_channel == NULL);
+    for ( i = 0; i < nr_irqs; i++ )
+        irq_channel[i] = -1;
+
+    cfg = hpet_read32(HPET_CFG);
+
     num_hpets_used = hpet_fsb_cap_lookup();
     if ( num_hpets_used > 0 )
     {
         /* Stop HPET legacy interrupts */
-        cfg = hpet_read32(HPET_CFG);
         cfg &= ~HPET_CFG_LEGACY;
-        hpet_write32(cfg, HPET_CFG);
+        n = num_hpets_used;
+    }
+    else
+    {
+        xfree(irq_channel);
+        irq_channel = NULL;
 
-        for ( i = 0; i < num_hpets_used; i++ )
-        {
-            /* set HPET Tn as oneshot */
-            cfg = hpet_read32(HPET_Tn_CFG(hpet_events[i].idx));
-            cfg &= ~HPET_TN_PERIODIC;
-            cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-            hpet_write32(cfg, HPET_Tn_CFG(hpet_events[i].idx));
-  
-            hpet_events[i].mult = div_sc((unsigned long)hpet_rate,
-                                         1000000000ul, 32);
-            hpet_events[i].shift = 32;
-            hpet_events[i].next_event = STIME_MAX;
-            spin_lock_init(&hpet_events[i].lock);
-            rwlock_init(&hpet_events[i].cpumask_lock);
-            wmb();
-            hpet_events[i].event_handler = handle_hpet_broadcast;
-        }
+        hpet_id = hpet_read32(HPET_ID);
+        if ( !(hpet_id & HPET_ID_LEGSUP) )
+            return;
 
-        return;
+        /* Start HPET legacy interrupts */
+        cfg |= HPET_CFG_LEGACY;
+        n = 1;
+        hpet_events->idx = 0;
+
+        if ( !force_hpet_broadcast )
+            pv_rtc_handler = handle_rtc_once;
     }
 
-    if ( legacy_hpet_event.flags & HPET_EVT_DISABLE )
-        return;
-
-    hpet_id = hpet_read32(HPET_ID);
-    if ( !(hpet_id & HPET_ID_LEGSUP) )
-        return;
-
-    /* Start HPET legacy interrupts */
-    cfg = hpet_read32(HPET_CFG);
-    cfg |= HPET_CFG_LEGACY;
     hpet_write32(cfg, HPET_CFG);
 
-    /* set HPET T0 as oneshot */
-    cfg = hpet_read32(HPET_T0_CFG);
-    cfg &= ~HPET_TN_PERIODIC;
-    cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-    hpet_write32(cfg, HPET_T0_CFG);
+    for ( i = 0; i < n; i++ )
+    {
+        /* set HPET Tn as oneshot */
+        cfg = hpet_read32(HPET_Tn_CFG(hpet_events[i].idx));
+        cfg &= ~HPET_TN_PERIODIC;
+        cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+        hpet_write32(cfg, HPET_Tn_CFG(hpet_events[i].idx));
 
-    /*
-     * The period is a femto seconds value. We need to calculate the scaled
-     * math multiplication factor for nanosecond to hpet tick conversion.
-     */
-    legacy_hpet_event.mult = div_sc((unsigned long)hpet_rate, 1000000000ul, 
32);
-    legacy_hpet_event.shift = 32;
-    legacy_hpet_event.next_event = STIME_MAX;
-    legacy_hpet_event.idx = 0;
-    legacy_hpet_event.flags = 0;
-    spin_lock_init(&legacy_hpet_event.lock);
-    rwlock_init(&legacy_hpet_event.cpumask_lock);
-    wmb();
-    legacy_hpet_event.event_handler = handle_hpet_broadcast;
+        /*
+         * The period is a femto seconds value. We need to calculate the scaled
+         * math multiplication factor for nanosecond to hpet tick conversion.
+         */
+        hpet_events[i].mult = div_sc((unsigned long)hpet_rate,
+                                     1000000000ul, 32);
+        hpet_events[i].shift = 32;
+        hpet_events[i].next_event = STIME_MAX;
+        spin_lock_init(&hpet_events[i].lock);
+        rwlock_init(&hpet_events[i].cpumask_lock);
+        wmb();
+        hpet_events[i].event_handler = handle_hpet_broadcast;
+    }
 
-    if ( !force_hpet_broadcast )
-        pv_rtc_handler = handle_rtc_once;
+    if ( !num_hpets_used )
+        hpet_events->flags = HPET_EVT_LEGACY;
+}
+
+void hpet_broadcast_resume(void)
+{
+    u32 cfg;
+    unsigned int i, n;
+
+    hpet_resume();
+
+    cfg = hpet_read32(HPET_CFG);
+
+    if ( num_hpets_used > 0 )
+    {
+        /* Stop HPET legacy interrupts */
+        cfg &= ~HPET_CFG_LEGACY;
+        n = num_hpets_used;
+    }
+    else if ( hpet_events->flags & HPET_EVT_DISABLE )
+        return;
+    else
+    {
+        /* Start HPET legacy interrupts */
+        cfg |= HPET_CFG_LEGACY;
+        n = 1;
+    }
+
+    hpet_write32(cfg, HPET_CFG);
+
+    for ( i = 0; i < n; i++ )
+    {
+        if ( hpet_events[i].irq >= 0 )
+            __hpet_setup_msi_irq(hpet_events[i].irq);
+
+        /* set HPET Tn as oneshot */
+        cfg = hpet_read32(HPET_Tn_CFG(hpet_events[i].idx));
+        cfg &= ~HPET_TN_PERIODIC;
+        cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+        hpet_write32(cfg, HPET_Tn_CFG(hpet_events[i].idx));
+
+        hpet_events[i].next_event = STIME_MAX;
+    }
 }
 
 void hpet_disable_legacy_broadcast(void)
@@ -647,21 +668,24 @@
     u32 cfg;
     unsigned long flags;
 
-    spin_lock_irqsave(&legacy_hpet_event.lock, flags);
+    if ( !(hpet_events->flags & HPET_EVT_LEGACY) )
+        return;
 
-    legacy_hpet_event.flags |= HPET_EVT_DISABLE;
+    spin_lock_irqsave(&hpet_events->lock, flags);
+
+    hpet_events->flags |= HPET_EVT_DISABLE;
 
     /* disable HPET T0 */
-    cfg = hpet_read32(HPET_T0_CFG);
+    cfg = hpet_read32(HPET_Tn_CFG(0));
     cfg &= ~HPET_TN_ENABLE;
-    hpet_write32(cfg, HPET_T0_CFG);
+    hpet_write32(cfg, HPET_Tn_CFG(0));
 
     /* Stop HPET legacy interrupts */
     cfg = hpet_read32(HPET_CFG);
     cfg &= ~HPET_CFG_LEGACY;
     hpet_write32(cfg, HPET_CFG);
 
-    spin_unlock_irqrestore(&legacy_hpet_event.lock, flags);
+    spin_unlock_irqrestore(&hpet_events->lock, flags);
 
     smp_send_event_check_mask(&cpu_online_map);
 }
@@ -679,7 +703,7 @@
 
     ASSERT(!local_irq_is_enabled());
 
-    if ( ch != &legacy_hpet_event )
+    if ( !(ch->flags & HPET_EVT_LEGACY) )
     {
         spin_lock(&ch->lock);
         hpet_attach_channel(cpu, ch);
@@ -717,7 +741,7 @@
     cpu_clear(cpu, ch->cpumask);
     read_unlock_irq(&ch->cpumask_lock);
 
-    if ( ch != &legacy_hpet_event )
+    if ( !(ch->flags & HPET_EVT_LEGACY) )
     {
         spin_lock_irq(&ch->lock);
         hpet_detach_channel(cpu, ch);
@@ -727,7 +751,7 @@
 
 int hpet_broadcast_is_available(void)
 {
-    return (legacy_hpet_event.event_handler == handle_hpet_broadcast
+    return ((hpet_events->flags & HPET_EVT_LEGACY)
             || num_hpets_used > 0);
 }
 
@@ -735,22 +759,20 @@
 {
     this_cpu(irq_count)--;
 
-    if ( !legacy_hpet_event.event_handler )
+    if ( (hpet_events->flags & (HPET_EVT_DISABLE|HPET_EVT_LEGACY)) !=
+         HPET_EVT_LEGACY )
         return 0;
-    legacy_hpet_event.event_handler(&legacy_hpet_event);
+    hpet_events->event_handler(hpet_events);
     return 1;
 }
 
-u64 hpet_setup(void)
+u64 __init hpet_setup(void)
 {
-    static u64 hpet_rate;
-    static u32 system_reset_latch;
-    u32 hpet_id, hpet_period, cfg;
-    int i;
+    static u64 __initdata hpet_rate;
+    u32 hpet_id, hpet_period;
 
-    if ( system_reset_latch == system_reset_counter )
+    if ( hpet_rate )
         return hpet_rate;
-    system_reset_latch = system_reset_counter;
 
     if ( hpet_address == 0 )
         return 0;
@@ -772,10 +794,29 @@
         return 0;
     }
 
+    hpet_resume();
+
+    hpet_rate = 1000000000000000ULL; /* 10^15 */
+    (void)do_div(hpet_rate, hpet_period);
+
+    return hpet_rate;
+}
+
+void hpet_resume(void)
+{
+    static u32 system_reset_latch;
+    u32 hpet_id, cfg;
+    unsigned int i;
+
+    if ( system_reset_latch == system_reset_counter )
+        return;
+    system_reset_latch = system_reset_counter;
+
     cfg = hpet_read32(HPET_CFG);
     cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
     hpet_write32(cfg, HPET_CFG);
 
+    hpet_id = hpet_read32(HPET_ID);
     for ( i = 0; i <= ((hpet_id >> 8) & 31); i++ )
     {
         cfg = hpet_read32(HPET_Tn_CFG(i));
@@ -786,9 +827,4 @@
     cfg = hpet_read32(HPET_CFG);
     cfg |= HPET_CFG_ENABLE;
     hpet_write32(cfg, HPET_CFG);
-
-    hpet_rate = 1000000000000000ULL; /* 10^15 */
-    (void)do_div(hpet_rate, hpet_period);
-
-    return hpet_rate;
 }
diff -r 87aa1277eae0 -r 5263151fba9b xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Sat Mar 12 13:19:02 2011 +0000
+++ b/xen/arch/x86/time.c       Sat Mar 12 13:19:34 2011 +0000
@@ -21,6 +21,7 @@
 #include <xen/smp.h>
 #include <xen/irq.h>
 #include <xen/softirq.h>
+#include <xen/symbols.h>
 #include <xen/keyhandler.h>
 #include <xen/guest_access.h>
 #include <asm/io.h>
@@ -374,10 +375,7 @@
 
 static void resume_hpet(struct platform_timesource *pts)
 {
-    u64 hpet_rate = hpet_setup();
-
-    BUG_ON(hpet_rate == 0);
-    pts->frequency = hpet_rate;
+    hpet_resume();
 }
 
 static struct platform_timesource __initdata plt_hpet =
@@ -1440,10 +1438,12 @@
 }
 
 /* keep pit enabled for pit_broadcast working while cpuidle enabled */
-static int disable_pit_irq(void)
+static int _disable_pit_irq(void(*hpet_broadcast_setup)(void))
 {
+    int ret = 1;
+
     if ( using_pit || !cpu_has_apic )
-        return 0;
+        return -1;
 
     /*
      * If we do not rely on PIT CH0 then we can use HPET for one-shot timer 
@@ -1453,20 +1453,16 @@
      */
     if ( xen_cpuidle && !boot_cpu_has(X86_FEATURE_ARAT) )
     {
-        hpet_broadcast_init();
+        hpet_broadcast_setup();
         if ( !hpet_broadcast_is_available() )
         {
-            if ( xen_cpuidle == -1 )
+            if ( xen_cpuidle > 0 )
             {
-                xen_cpuidle = 0;
-                printk("CPUIDLE: disabled due to no HPET. "
-                       "Force enable with 'cpuidle'.\n");
+                print_symbol("%s() failed, turning to PIT broadcast\n",
+                             (unsigned long)hpet_broadcast_setup);
+                return -1;
             }
-            else
-            {
-                printk("HPET broadcast init failed, turn to PIT broadcast.\n");
-                return 0;
-            }
+            ret = 0;
         }
     }
 
@@ -1475,6 +1471,18 @@
     outb_p(0, PIT_CH0);
     outb_p(0, PIT_CH0);
 
+    return ret;
+}
+
+static int __init disable_pit_irq(void)
+{
+    if ( !_disable_pit_irq(hpet_broadcast_init) )
+    {
+        xen_cpuidle = 0;
+        printk("CPUIDLE: disabled due to no HPET. "
+               "Force enable with 'cpuidle'.\n");
+    }
+
     return 0;
 }
 __initcall(disable_pit_irq);
@@ -1541,7 +1549,8 @@
 
     resume_platform_timer();
 
-    disable_pit_irq();
+    if ( !_disable_pit_irq(hpet_broadcast_resume) )
+        BUG();
 
     init_percpu_time();
 
diff -r 87aa1277eae0 -r 5263151fba9b xen/include/asm-x86/hpet.h
--- a/xen/include/asm-x86/hpet.h        Sat Mar 12 13:19:02 2011 +0000
+++ b/xen/include/asm-x86/hpet.h        Sat Mar 12 13:19:34 2011 +0000
@@ -14,19 +14,9 @@
 #define HPET_CFG       0x010
 #define HPET_STATUS    0x020
 #define HPET_COUNTER   0x0f0
-#define HPET_T0_CFG    0x100
-#define HPET_T0_CMP    0x108
-#define HPET_T0_ROUTE  0x110
-#define HPET_T1_CFG    0x120
-#define HPET_T1_CMP    0x128
-#define HPET_T1_ROUTE  0x130
-#define HPET_T2_CFG    0x140
-#define HPET_T2_CMP    0x148
-#define HPET_T2_ROUTE  0x150
-
-#define HPET_Tn_CFG(n)      (HPET_T0_CFG + n * 0x20)
-#define HPET_Tn_CMP(n)      (HPET_T0_CMP + n * 0x20)
-#define HPET_Tn_ROUTE(n)    (HPET_T0_ROUTE + n * 0x20)
+#define HPET_Tn_CFG(n)          (0x100 + (n) * 0x20)
+#define HPET_Tn_CMP(n)          (0x108 + (n) * 0x20)
+#define HPET_Tn_ROUTE(n)        (0x110 + (n) * 0x20)
 
 #define HPET_ID_VENDOR 0xffff0000
 #define HPET_ID_LEGSUP 0x00008000
@@ -65,6 +55,7 @@
  * Return value is zero if HPET is unavailable.
  */
 u64 hpet_setup(void);
+void hpet_resume(void);
 
 /*
  * Callback from legacy timer (PIT channel 0) IRQ handler.
@@ -77,6 +68,7 @@
  * rather than using the LAPIC timer. Used for Cx state entry.
  */
 void hpet_broadcast_init(void);
+void hpet_broadcast_resume(void);
 void hpet_broadcast_enter(void);
 void hpet_broadcast_exit(void);
 int hpet_broadcast_is_available(void);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86/HPET: cleanup, Xen patchbot-unstable <=