From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750769AbVKKOHv (ORCPT ); Fri, 11 Nov 2005 09:07:51 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750773AbVKKOHv (ORCPT ); Fri, 11 Nov 2005 09:07:51 -0500 Received: from cantor.suse.de ([195.135.220.2]:15269 "EHLO mx1.suse.de") by vger.kernel.org with ESMTP id S1750769AbVKKOHu (ORCPT ); Fri, 11 Nov 2005 09:07:50 -0500 Date: Fri, 11 Nov 2005 15:07:48 +0100 Message-ID: From: Takashi Iwai To: Marek Szuba Cc: linux-kernel@vger.kernel.org Subject: Re: ALSA in 2.6.14: RTC timer breaks MIDI In-Reply-To: References: User-Agent: Wanderlust/2.12.0 (Your Wildest Dreams) SEMI/1.14.6 (Maruoka) FLIM/1.14.7 (=?ISO-8859-4?Q?Sanj=F2?=) APEL/10.6 MULE XEmacs/21.5 (beta18) (chestnut) (+CVS-20041021) (i386-suse-linux) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org At Thu, 10 Nov 2005 17:48:04 +0100 (CET), Marek Szuba wrote: > > (I'm having problems with access to the ALSA bug tracker, that's why I'm > reporting this issue here) > > Hello everyone, > > A couple of days ago I tried to play a MIDI file on a 2.6.14 box with > emu10k1 for sound (Audigy 2 ZS) and was surprised to hear that the > sequencer no longer works - or to be exact, when having it play any MIDI > song it only starts playing the first note in each channel and leaves them > like that, playing the same tones until the player's closed. Going back to > 2.6.13 made the problem go away; on the other hand, even an upgrade of > ALSA userspace components to the latest version doesn't help with 2.6.14. A known problem. Try the patch below. Takashi --- diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -149,8 +149,22 @@ static void get_rtc_alm_time (struct rtc #ifdef RTC_IRQ static void rtc_dropped_irq(unsigned long data); -static void set_rtc_irq_bit(unsigned char bit); -static void mask_rtc_irq_bit(unsigned char bit); +static void set_rtc_irq_bit_locked(unsigned char bit); +static void mask_rtc_irq_bit_locked(unsigned char bit); + +static inline void set_rtc_irq_bit(unsigned char bit) +{ + spin_lock_irq(&rtc_lock); + set_rtc_irq_bit_locked(bit); + spin_unlock_irq(&rtc_lock); +} + +static void mask_rtc_irq_bit(unsigned char bit) +{ + spin_lock_irq(&rtc_lock); + mask_rtc_irq_bit_locked(bit); + spin_unlock_irq(&rtc_lock); +} #endif static int rtc_proc_open(struct inode *inode, struct file *file); @@ -401,18 +415,19 @@ static int rtc_do_ioctl(unsigned int cmd } case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ { - mask_rtc_irq_bit(RTC_PIE); + unsigned long flags; /* can be called from isr via rtc_control() */ + spin_lock_irqsave (&rtc_lock, flags); + mask_rtc_irq_bit_locked(RTC_PIE); if (rtc_status & RTC_TIMER_ON) { - spin_lock_irq (&rtc_lock); rtc_status &= ~RTC_TIMER_ON; del_timer(&rtc_irq_timer); - spin_unlock_irq (&rtc_lock); } + spin_unlock_irqrestore (&rtc_lock, flags); return 0; } case RTC_PIE_ON: /* Allow periodic ints */ { - + unsigned long flags; /* can be called from isr via rtc_control() */ /* * We don't really want Joe User enabling more * than 64Hz of interrupts on a multi-user machine. @@ -421,14 +436,14 @@ static int rtc_do_ioctl(unsigned int cmd (!capable(CAP_SYS_RESOURCE))) return -EACCES; + spin_lock_irqsave (&rtc_lock, flags); if (!(rtc_status & RTC_TIMER_ON)) { - spin_lock_irq (&rtc_lock); rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; add_timer(&rtc_irq_timer); rtc_status |= RTC_TIMER_ON; - spin_unlock_irq (&rtc_lock); } - set_rtc_irq_bit(RTC_PIE); + set_rtc_irq_bit_locked(RTC_PIE); + spin_unlock_irqrestore (&rtc_lock, flags); return 0; } case RTC_UIE_OFF: /* Mask ints from RTC updates. */ @@ -609,6 +624,7 @@ static int rtc_do_ioctl(unsigned int cmd { int tmp = 0; unsigned char val; + unsigned long flags; /* can be called from isr via rtc_control() */ /* * The max we can do is 8192Hz. @@ -631,9 +647,9 @@ static int rtc_do_ioctl(unsigned int cmd if (arg != (1<