[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-4.2-testing] x86/HPET: fix FSB interrupt masking
# HG changeset patch # User Jan Beulich <jbeulich@xxxxxxxx> # Date 1357717796 -3600 # Node ID 9abea6220b1110e4ca6322afb2f58edc7eef76b4 # Parent 7dad27b2bcc7ec42c6f76b04c3a5a94bc6b49a0f x86/HPET: fix FSB interrupt masking HPET_TN_FSB is not really suitable for masking interrupts - it merely switches between the two delivery methods. The right way of masking is through the HPET_TN_ENABLE bit (which really is an interrupt enable, not a counter enable or some such). This is even more so with certain chip sets not even allowing HPET_TN_FSB to be cleared on some of the channels. Further, all the setup of the channel should happen before actually enabling the interrupt, which requires splitting legacy and FSB logic. Finally this also fixes an S3 resume problem (HPET_TN_FSB did not get set in hpet_broadcast_resume(), and hpet_msi_unmask() doesn't get called from the general resume code either afaict). Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Keir Fraser <keir@xxxxxxx> xen-unstable changeset: 26183:c139ca92edca xen-unstable date: Thu Nov 22 09:03:23 UTC 2012 --- diff -r 7dad27b2bcc7 -r 9abea6220b11 xen/arch/x86/hpet.c --- a/xen/arch/x86/hpet.c Mon Jan 07 14:24:36 2013 +0100 +++ b/xen/arch/x86/hpet.c Wed Jan 09 08:49:56 2013 +0100 @@ -236,7 +236,7 @@ static void hpet_msi_unmask(struct irq_d struct hpet_event_channel *ch = desc->action->dev_id; cfg = hpet_read32(HPET_Tn_CFG(ch->idx)); - cfg |= HPET_TN_FSB; + cfg |= HPET_TN_ENABLE; hpet_write32(cfg, HPET_Tn_CFG(ch->idx)); } @@ -246,7 +246,7 @@ static void hpet_msi_mask(struct irq_des struct hpet_event_channel *ch = desc->action->dev_id; cfg = hpet_read32(HPET_Tn_CFG(ch->idx)); - cfg &= ~HPET_TN_FSB; + cfg &= ~HPET_TN_ENABLE; hpet_write32(cfg, HPET_Tn_CFG(ch->idx)); } @@ -319,8 +319,14 @@ static void __hpet_setup_msi_irq(struct static int __init hpet_setup_msi_irq(unsigned int irq, struct hpet_event_channel *ch) { int ret; + u32 cfg = hpet_read32(HPET_Tn_CFG(ch->idx)); irq_desc_t *desc = irq_to_desc(irq); + /* set HPET Tn as oneshot */ + cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); + cfg |= HPET_TN_FSB | HPET_TN_32BIT; + hpet_write32(cfg, HPET_Tn_CFG(ch->idx)); + desc->handler = &hpet_msi_type; ret = request_irq(irq, hpet_interrupt_handler, 0, "HPET", ch); if ( ret < 0 ) @@ -541,11 +547,14 @@ void __init hpet_broadcast_init(void) for ( i = 0; i < n; i++ ) { - /* set HPET Tn as oneshot */ - cfg = hpet_read32(HPET_Tn_CFG(hpet_events[i].idx)); - cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); - cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; - hpet_write32(cfg, HPET_Tn_CFG(hpet_events[i].idx)); + if ( i == 0 && (cfg & HPET_CFG_LEGACY) ) + { + /* set HPET T0 as oneshot */ + cfg = hpet_read32(HPET_Tn_CFG(0)); + cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); + cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; + hpet_write32(cfg, HPET_Tn_CFG(0)); + } /* * The period is a femto seconds value. We need to calculate the scaled @@ -602,6 +611,8 @@ void hpet_broadcast_resume(void) cfg = hpet_read32(HPET_Tn_CFG(hpet_events[i].idx)); cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; + if ( !(hpet_events[i].flags & HPET_EVT_LEGACY) ) + cfg |= HPET_TN_FSB; hpet_write32(cfg, HPET_Tn_CFG(hpet_events[i].idx)); hpet_events[i].next_event = STIME_MAX; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |