From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933796Ab1DNS1Y (ORCPT ); Thu, 14 Apr 2011 14:27:24 -0400 Received: from mail.windriver.com ([147.11.1.11]:38074 "EHLO mail.windriver.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933049Ab1DNRqX (ORCPT ); Thu, 14 Apr 2011 13:46:23 -0400 From: Paul Gortmaker To: stable@kernel.org, linux-kernel@vger.kernel.org Cc: stable-review@kernel.org, Clemens Ladisch , Ingo Molnar , Thomas Gleixner , john stultz , Bob Picco , Andrew Morton , Linus Torvalds , Paul Gortmaker Subject: [34-longterm 029/209] hpet: fix unwanted interrupt due to stale irq status bit Date: Thu, 14 Apr 2011 13:40:59 -0400 Message-Id: <1302803039-9400-30-git-send-email-paul.gortmaker@windriver.com> X-Mailer: git-send-email 1.7.4.4 In-Reply-To: <1302803039-9400-1-git-send-email-paul.gortmaker@windriver.com> References: <1302803039-9400-1-git-send-email-paul.gortmaker@windriver.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Clemens Ladisch ===================================================================== | This is a commit scheduled for the next v2.6.34 longterm release. | | If you see a problem with using this for longterm, please comment.| ===================================================================== commit 96e9694df446d1154ec2f4fdba8908588b9cba38 upstream. Jaswinder Singh Rajput wrote: > By executing Documentation/timers/hpet_example.c > > for polling, I requested for 3 iterations but it seems iteration work > for only 2 as first expired time is always very small. > > # ./hpet_example poll /dev/hpet 10 3 > -hpet: executing poll > hpet_poll: info.hi_flags 0x0 > hpet_poll: expired time = 0x13 > hpet_poll: revents = 0x1 > hpet_poll: data 0x1 > hpet_poll: expired time = 0x1868c > hpet_poll: revents = 0x1 > hpet_poll: data 0x1 > hpet_poll: expired time = 0x18645 > hpet_poll: revents = 0x1 > hpet_poll: data 0x1 Clearing the HPET interrupt enable bit disables interrupt generation but does not disable the timer, so the interrupt status bit will still be set when the timer elapses. If another interrupt arrives before the timer has been correctly programmed (due to some other device on the same interrupt line, or CONFIG_DEBUG_SHIRQ), this results in an extra unwanted interrupt event because the status bit is likely to be set from comparator matches that happened before the device was opened. Therefore, we have to ensure that the interrupt status bit is and stays cleared until we actually program the timer. Signed-off-by: Clemens Ladisch Reported-by: Jaswinder Singh Rajput Cc: Ingo Molnar Cc: Thomas Gleixner Cc: john stultz Cc: Bob Picco Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Paul Gortmaker --- drivers/char/hpet.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 9ded667..7447ffa 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -475,6 +475,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) if (irq) { unsigned long irq_flags; + if (devp->hd_flags & HPET_SHARED_IRQ) { + /* + * To prevent the interrupt handler from seeing an + * unwanted interrupt status bit, program the timer + * so that it will not fire in the near future ... + */ + writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK, + &timer->hpet_config); + write_counter(read_counter(&hpet->hpet_mc), + &timer->hpet_compare); + /* ... and clear any left-over status. */ + isr = 1 << (devp - devp->hd_hpets->hp_dev); + writel(isr, &hpet->hpet_isr); + } + sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); irq_flags = devp->hd_flags & HPET_SHARED_IRQ ? IRQF_SHARED : IRQF_DISABLED; -- 1.7.4.4