diff options
author | James Courtier-Dutton <James@superbug.co.uk> | 2007-11-10 12:55:14 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:30:24 -0500 |
commit | c94fa4c9168e51a8dab8e72cb9f0d89673fc8d8c (patch) | |
tree | 08169553a3b69a284b322941131f406661e499e8 | |
parent | 3839e4f136d6da3dc85d237aa9569ee94bfea763 (diff) |
[ALSA] emu10k1: General cleanup, add new locks, fix alsa bug#3501, kernel bug#9304.
Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | include/sound/emu10k1.h | 2 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_callback.c | 15 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 6 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_synth.c | 45 | ||||
-rw-r--r-- | sound/pci/emu10k1/io.c | 52 | ||||
-rw-r--r-- | sound/pci/emu10k1/irq.c | 8 |
6 files changed, 82 insertions, 46 deletions
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 494648dd7073..7b7b9b13b4dd 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h | |||
@@ -1742,6 +1742,8 @@ struct snd_emu10k1 { | |||
1742 | spinlock_t reg_lock; | 1742 | spinlock_t reg_lock; |
1743 | spinlock_t emu_lock; | 1743 | spinlock_t emu_lock; |
1744 | spinlock_t voice_lock; | 1744 | spinlock_t voice_lock; |
1745 | spinlock_t spi_lock; /* serialises access to spi port */ | ||
1746 | spinlock_t i2c_lock; /* serialises access to i2c port */ | ||
1745 | 1747 | ||
1746 | struct snd_emu10k1_voice voices[NUM_G]; | 1748 | struct snd_emu10k1_voice voices[NUM_G]; |
1747 | struct snd_emu10k1_voice p16v_voices[4]; | 1749 | struct snd_emu10k1_voice p16v_voices[4]; |
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 01965bd99966..45088ebcce50 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c | |||
@@ -35,9 +35,9 @@ struct best_voice { | |||
35 | /* | 35 | /* |
36 | * prototypes | 36 | * prototypes |
37 | */ | 37 | */ |
38 | static void lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, | 38 | static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw, |
39 | struct best_voice *best, int active_only); | 39 | struct best_voice *best, int active_only); |
40 | static struct snd_emux_voice *get_voice(struct snd_emux *emu, | 40 | static struct snd_emux_voice *get_voice(struct snd_emux *emux, |
41 | struct snd_emux_port *port); | 41 | struct snd_emux_port *port); |
42 | static int start_voice(struct snd_emux_voice *vp); | 42 | static int start_voice(struct snd_emux_voice *vp); |
43 | static void trigger_voice(struct snd_emux_voice *vp); | 43 | static void trigger_voice(struct snd_emux_voice *vp); |
@@ -45,7 +45,6 @@ static void release_voice(struct snd_emux_voice *vp); | |||
45 | static void update_voice(struct snd_emux_voice *vp, int update); | 45 | static void update_voice(struct snd_emux_voice *vp, int update); |
46 | static void terminate_voice(struct snd_emux_voice *vp); | 46 | static void terminate_voice(struct snd_emux_voice *vp); |
47 | static void free_voice(struct snd_emux_voice *vp); | 47 | static void free_voice(struct snd_emux_voice *vp); |
48 | |||
49 | static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); | 48 | static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); |
50 | static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); | 49 | static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); |
51 | static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); | 50 | static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); |
@@ -75,9 +74,9 @@ static struct snd_emux_operators emu10k1_ops = { | |||
75 | }; | 74 | }; |
76 | 75 | ||
77 | void | 76 | void |
78 | snd_emu10k1_ops_setup(struct snd_emux *emu) | 77 | snd_emu10k1_ops_setup(struct snd_emux *emux) |
79 | { | 78 | { |
80 | emu->ops = emu10k1_ops; | 79 | emux->ops = emu10k1_ops; |
81 | } | 80 | } |
82 | 81 | ||
83 | 82 | ||
@@ -166,7 +165,11 @@ free_voice(struct snd_emux_voice *vp) | |||
166 | struct snd_emu10k1 *hw; | 165 | struct snd_emu10k1 *hw; |
167 | 166 | ||
168 | hw = vp->hw; | 167 | hw = vp->hw; |
169 | if (vp->ch >= 0) { | 168 | /* FIXME: emu10k1_synth is broken. */ |
169 | /* This can get called with hw == 0 */ | ||
170 | /* Problem apparent on plug, unplug then plug */ | ||
171 | /* on the Audigy 2 ZS Notebook. */ | ||
172 | if (hw && (vp->ch >= 0)) { | ||
170 | snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); | 173 | snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); |
171 | snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); | 174 | snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); |
172 | // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); | 175 | // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 7e46325974a5..f29caf1afe06 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -259,7 +259,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
259 | * GPIO7: Unknown | 259 | * GPIO7: Unknown |
260 | */ | 260 | */ |
261 | outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ | 261 | outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ |
262 | |||
263 | } | 262 | } |
264 | if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ | 263 | if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ |
265 | int size, n; | 264 | int size, n; |
@@ -275,7 +274,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
275 | emu->i2c_capture_volume[n][0]= 0xcf; | 274 | emu->i2c_capture_volume[n][0]= 0xcf; |
276 | emu->i2c_capture_volume[n][1]= 0xcf; | 275 | emu->i2c_capture_volume[n][1]= 0xcf; |
277 | } | 276 | } |
278 | |||
279 | } | 277 | } |
280 | 278 | ||
281 | 279 | ||
@@ -653,6 +651,8 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) | |||
653 | value = inl(special_port); | 651 | value = inl(special_port); |
654 | 652 | ||
655 | snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ | 653 | snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ |
654 | /* Delay to give time for ADC chip to switch on. It needs 113ms */ | ||
655 | msleep(200); | ||
656 | return 0; | 656 | return 0; |
657 | } | 657 | } |
658 | 658 | ||
@@ -1717,6 +1717,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1717 | emu->card = card; | 1717 | emu->card = card; |
1718 | spin_lock_init(&emu->reg_lock); | 1718 | spin_lock_init(&emu->reg_lock); |
1719 | spin_lock_init(&emu->emu_lock); | 1719 | spin_lock_init(&emu->emu_lock); |
1720 | spin_lock_init(&emu->spi_lock); | ||
1721 | spin_lock_init(&emu->i2c_lock); | ||
1720 | spin_lock_init(&emu->voice_lock); | 1722 | spin_lock_init(&emu->voice_lock); |
1721 | spin_lock_init(&emu->synth_lock); | 1723 | spin_lock_init(&emu->synth_lock); |
1722 | spin_lock_init(&emu->memblk_lock); | 1724 | spin_lock_init(&emu->memblk_lock); |
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c index 204995a1dfbd..ad7b71491fc4 100644 --- a/sound/pci/emu10k1/emu10k1_synth.c +++ b/sound/pci/emu10k1/emu10k1_synth.c | |||
@@ -30,7 +30,7 @@ MODULE_LICENSE("GPL"); | |||
30 | */ | 30 | */ |
31 | static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) | 31 | static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) |
32 | { | 32 | { |
33 | struct snd_emux *emu; | 33 | struct snd_emux *emux; |
34 | struct snd_emu10k1 *hw; | 34 | struct snd_emu10k1 *hw; |
35 | struct snd_emu10k1_synth_arg *arg; | 35 | struct snd_emu10k1_synth_arg *arg; |
36 | unsigned long flags; | 36 | unsigned long flags; |
@@ -46,53 +46,56 @@ static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) | |||
46 | else if (arg->max_voices > 64) | 46 | else if (arg->max_voices > 64) |
47 | arg->max_voices = 64; | 47 | arg->max_voices = 64; |
48 | 48 | ||
49 | if (snd_emux_new(&emu) < 0) | 49 | if (snd_emux_new(&emux) < 0) |
50 | return -ENOMEM; | 50 | return -ENOMEM; |
51 | 51 | ||
52 | snd_emu10k1_ops_setup(emu); | 52 | snd_emu10k1_ops_setup(emux); |
53 | emu->hw = hw = arg->hwptr; | 53 | hw = arg->hwptr; |
54 | emu->max_voices = arg->max_voices; | 54 | emux->hw = hw; |
55 | emu->num_ports = arg->seq_ports; | 55 | emux->max_voices = arg->max_voices; |
56 | emu->pitch_shift = -501; | 56 | emux->num_ports = arg->seq_ports; |
57 | emu->memhdr = hw->memhdr; | 57 | emux->pitch_shift = -501; |
58 | emu->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; /* maximum two ports */ | 58 | emux->memhdr = hw->memhdr; |
59 | emu->midi_devidx = hw->audigy ? 2 : 1; /* audigy has two external midis */ | 59 | /* maximum two ports */ |
60 | emu->linear_panning = 0; | 60 | emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; |
61 | emu->hwdep_idx = 2; /* FIXED */ | 61 | /* audigy has two external midis */ |
62 | 62 | emux->midi_devidx = hw->audigy ? 2 : 1; | |
63 | if (snd_emux_register(emu, dev->card, arg->index, "Emu10k1") < 0) { | 63 | emux->linear_panning = 0; |
64 | snd_emux_free(emu); | 64 | emux->hwdep_idx = 2; /* FIXED */ |
65 | |||
66 | if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) { | ||
67 | snd_emux_free(emux); | ||
65 | return -ENOMEM; | 68 | return -ENOMEM; |
66 | } | 69 | } |
67 | 70 | ||
68 | spin_lock_irqsave(&hw->voice_lock, flags); | 71 | spin_lock_irqsave(&hw->voice_lock, flags); |
69 | hw->synth = emu; | 72 | hw->synth = emux; |
70 | hw->get_synth_voice = snd_emu10k1_synth_get_voice; | 73 | hw->get_synth_voice = snd_emu10k1_synth_get_voice; |
71 | spin_unlock_irqrestore(&hw->voice_lock, flags); | 74 | spin_unlock_irqrestore(&hw->voice_lock, flags); |
72 | 75 | ||
73 | dev->driver_data = emu; | 76 | dev->driver_data = emux; |
74 | 77 | ||
75 | return 0; | 78 | return 0; |
76 | } | 79 | } |
77 | 80 | ||
78 | static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) | 81 | static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) |
79 | { | 82 | { |
80 | struct snd_emux *emu; | 83 | struct snd_emux *emux; |
81 | struct snd_emu10k1 *hw; | 84 | struct snd_emu10k1 *hw; |
82 | unsigned long flags; | 85 | unsigned long flags; |
83 | 86 | ||
84 | if (dev->driver_data == NULL) | 87 | if (dev->driver_data == NULL) |
85 | return 0; /* not registered actually */ | 88 | return 0; /* not registered actually */ |
86 | 89 | ||
87 | emu = dev->driver_data; | 90 | emux = dev->driver_data; |
88 | 91 | ||
89 | hw = emu->hw; | 92 | hw = emux->hw; |
90 | spin_lock_irqsave(&hw->voice_lock, flags); | 93 | spin_lock_irqsave(&hw->voice_lock, flags); |
91 | hw->synth = NULL; | 94 | hw->synth = NULL; |
92 | hw->get_synth_voice = NULL; | 95 | hw->get_synth_voice = NULL; |
93 | spin_unlock_irqrestore(&hw->voice_lock, flags); | 96 | spin_unlock_irqrestore(&hw->voice_lock, flags); |
94 | 97 | ||
95 | snd_emux_free(emu); | 98 | snd_emux_free(emux); |
96 | return 0; | 99 | return 0; |
97 | } | 100 | } |
98 | 101 | ||
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index a02638350a0a..b5a802bdeb7c 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c | |||
@@ -70,6 +70,11 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i | |||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | unsigned int mask; | 71 | unsigned int mask; |
72 | 72 | ||
73 | if (!emu) { | ||
74 | snd_printk(KERN_ERR "ptr_write: emu is null!\n"); | ||
75 | dump_stack(); | ||
76 | return; | ||
77 | } | ||
73 | mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; | 78 | mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; |
74 | regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); | 79 | regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); |
75 | 80 | ||
@@ -134,15 +139,23 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, | |||
134 | unsigned int reset, set; | 139 | unsigned int reset, set; |
135 | unsigned int reg, tmp; | 140 | unsigned int reg, tmp; |
136 | int n, result; | 141 | int n, result; |
142 | int err = 0; | ||
143 | |||
144 | /* This function is not re-entrant, so protect against it. */ | ||
145 | spin_lock(&emu->spi_lock); | ||
137 | if (emu->card_capabilities->ca0108_chip) | 146 | if (emu->card_capabilities->ca0108_chip) |
138 | reg = 0x3c; /* PTR20, reg 0x3c */ | 147 | reg = 0x3c; /* PTR20, reg 0x3c */ |
139 | else { | 148 | else { |
140 | /* For other chip types the SPI register | 149 | /* For other chip types the SPI register |
141 | * is currently unknown. */ | 150 | * is currently unknown. */ |
142 | return 1; | 151 | err = 1; |
152 | goto spi_write_exit; | ||
153 | } | ||
154 | if (data > 0xffff) { | ||
155 | /* Only 16bit values allowed */ | ||
156 | err = 1; | ||
157 | goto spi_write_exit; | ||
143 | } | 158 | } |
144 | if (data > 0xffff) /* Only 16bit values allowed */ | ||
145 | return 1; | ||
146 | 159 | ||
147 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); | 160 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); |
148 | reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ | 161 | reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ |
@@ -160,11 +173,17 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, | |||
160 | break; | 173 | break; |
161 | } | 174 | } |
162 | } | 175 | } |
163 | if (result) /* Timed out */ | 176 | if (result) { |
164 | return 1; | 177 | /* Timed out */ |
178 | err = 1; | ||
179 | goto spi_write_exit; | ||
180 | } | ||
165 | snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); | 181 | snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); |
166 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ | 182 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ |
167 | return 0; | 183 | err = 0; |
184 | spi_write_exit: | ||
185 | spin_unlock(&emu->spi_lock); | ||
186 | return err; | ||
168 | } | 187 | } |
169 | 188 | ||
170 | /* The ADC does not support i2c read, so only write is implemented */ | 189 | /* The ADC does not support i2c read, so only write is implemented */ |
@@ -176,15 +195,17 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
176 | int timeout = 0; | 195 | int timeout = 0; |
177 | int status; | 196 | int status; |
178 | int retry; | 197 | int retry; |
198 | int err = 0; | ||
199 | |||
179 | if ((reg > 0x7f) || (value > 0x1ff)) { | 200 | if ((reg > 0x7f) || (value > 0x1ff)) { |
180 | snd_printk(KERN_ERR "i2c_write: invalid values.\n"); | 201 | snd_printk(KERN_ERR "i2c_write: invalid values.\n"); |
181 | return -EINVAL; | 202 | return -EINVAL; |
182 | } | 203 | } |
183 | 204 | ||
205 | /* This function is not re-entrant, so protect against it. */ | ||
206 | spin_lock(&emu->i2c_lock); | ||
207 | |||
184 | tmp = reg << 25 | value << 16; | 208 | tmp = reg << 25 | value << 16; |
185 | // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); | ||
186 | /* Not sure what this I2C channel controls. */ | ||
187 | /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */ | ||
188 | 209 | ||
189 | /* This controls the I2C connected to the WM8775 ADC Codec */ | 210 | /* This controls the I2C connected to the WM8775 ADC Codec */ |
190 | snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); | 211 | snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); |
@@ -192,17 +213,14 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
192 | 213 | ||
193 | for (retry = 0; retry < 10; retry++) { | 214 | for (retry = 0; retry < 10; retry++) { |
194 | /* Send the data to i2c */ | 215 | /* Send the data to i2c */ |
195 | //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0); | ||
196 | //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); | ||
197 | tmp = 0; | 216 | tmp = 0; |
198 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); | 217 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); |
199 | snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); | 218 | snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); |
200 | 219 | ||
201 | /* Wait till the transaction ends */ | 220 | /* Wait till the transaction ends */ |
202 | while (1) { | 221 | while (1) { |
203 | udelay(10); | 222 | mdelay(1); |
204 | status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); | 223 | status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); |
205 | // snd_printk("I2C:status=0x%x\n", status); | ||
206 | timeout++; | 224 | timeout++; |
207 | if ((status & I2C_A_ADC_START) == 0) | 225 | if ((status & I2C_A_ADC_START) == 0) |
208 | break; | 226 | break; |
@@ -219,10 +237,14 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
219 | 237 | ||
220 | if (retry == 10) { | 238 | if (retry == 10) { |
221 | snd_printk(KERN_ERR "Writing to ADC failed!\n"); | 239 | snd_printk(KERN_ERR "Writing to ADC failed!\n"); |
222 | return -EINVAL; | 240 | snd_printk(KERN_ERR "status=0x%x, reg=%d, value=%d\n", |
241 | status, reg, value); | ||
242 | /* dump_stack(); */ | ||
243 | err = -EINVAL; | ||
223 | } | 244 | } |
224 | 245 | ||
225 | return 0; | 246 | spin_unlock(&emu->i2c_lock); |
247 | return err; | ||
226 | } | 248 | } |
227 | 249 | ||
228 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) | 250 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) |
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 276d08c88f91..30bfed6f8339 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c | |||
@@ -34,9 +34,10 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) | |||
34 | struct snd_emu10k1 *emu = dev_id; | 34 | struct snd_emu10k1 *emu = dev_id; |
35 | unsigned int status, status2, orig_status, orig_status2; | 35 | unsigned int status, status2, orig_status, orig_status2; |
36 | int handled = 0; | 36 | int handled = 0; |
37 | int timeout = 0; | ||
37 | 38 | ||
38 | while ((status = inl(emu->port + IPR)) != 0) { | 39 | while (((status = inl(emu->port + IPR)) != 0) && (timeout < 1000)) { |
39 | //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status); | 40 | timeout++; |
40 | orig_status = status; | 41 | orig_status = status; |
41 | handled = 1; | 42 | handled = 1; |
42 | if ((status & 0xffffffff) == 0xffffffff) { | 43 | if ((status & 0xffffffff) == 0xffffffff) { |
@@ -200,5 +201,8 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) | |||
200 | } | 201 | } |
201 | outl(orig_status, emu->port + IPR); /* ack all */ | 202 | outl(orig_status, emu->port + IPR); /* ack all */ |
202 | } | 203 | } |
204 | if (timeout == 1000) | ||
205 | snd_printk(KERN_INFO "emu10k1 irq routine failure\n"); | ||
206 | |||
203 | return IRQ_RETVAL(handled); | 207 | return IRQ_RETVAL(handled); |
204 | } | 208 | } |