[PATCH] sound: fix hang in mpu401_uart.c

This fixes a hang in mpu401_uart.c that can occur when the mpu401 interface
is non-existent or otherwise doesn't respond to commands but we issue IO
anyway. snd_mpu401_uart_cmd now returns an error code that is passed up
the stack so that an open() will fail immediately in such cases.

Eventually discovered after wine/cxoffice would constantly cause hard
lockups on my desktop immediately after loading (emulating Windows too
well). Turned out that I'd recently moved my sound cards around and using
/dev/sequencer now talks to a sound card with a broken MPU.

This second version changes -EFAULT to -EIO and frees open resources on
error too. Test booted and seems to work ok.

Signed-off-by: Jon Masters <jcm@jonmasters.org>
Cc: Jaroslav Kysela <perex@suse.cz>
Acked-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Jon Masters and committed by Linus Torvalds 962f831f c79cfbac

+33 -9
+33 -9
sound/drivers/mpu401/mpu401_uart.c
··· 183 184 */ 185 186 - static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack) 187 { 188 unsigned long flags; 189 int timeout, ok; ··· 219 ok = 1; 220 } 221 spin_unlock_irqrestore(&mpu->input_lock, flags); 222 - if (! ok) 223 snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu))); 224 - // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu))); 225 } 226 227 /* ··· 238 if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) 239 return err; 240 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { 241 - snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1); 242 - snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1); 243 } 244 mpu->substream_input = substream; 245 set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); 246 return 0; 247 } 248 249 static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) ··· 262 if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) 263 return err; 264 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { 265 - snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1); 266 - snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1); 267 } 268 mpu->substream_output = substream; 269 set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); 270 return 0; 271 } 272 273 static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream) 274 { 275 struct snd_mpu401 *mpu; 276 277 mpu = substream->rmidi->private_data; 278 clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); 279 mpu->substream_input = NULL; 280 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) 281 - snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); 282 if (mpu->close_input) 283 mpu->close_input(mpu); 284 return 0; 285 } 286 287 static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) 288 { 289 struct snd_mpu401 *mpu; 290 291 mpu = substream->rmidi->private_data; 292 clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); 293 mpu->substream_output = NULL; 294 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) 295 - snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); 296 if (mpu->close_output) 297 mpu->close_output(mpu); 298 return 0; 299 } 300 ··· 339 snd_mpu401_uart_remove_timer(mpu, 1); 340 clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); 341 } 342 } 343 344 /*
··· 183 184 */ 185 186 + static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, 187 + int ack) 188 { 189 unsigned long flags; 190 int timeout, ok; ··· 218 ok = 1; 219 } 220 spin_unlock_irqrestore(&mpu->input_lock, flags); 221 + if (!ok) { 222 snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu))); 223 + return 1; 224 + } 225 + return 0; 226 } 227 228 /* ··· 235 if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) 236 return err; 237 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { 238 + if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) 239 + goto error_out; 240 + if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1)) 241 + goto error_out; 242 } 243 mpu->substream_input = substream; 244 set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); 245 return 0; 246 + 247 + error_out: 248 + if (mpu->open_input && mpu->close_input) 249 + mpu->close_input(mpu); 250 + return -EIO; 251 } 252 253 static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) ··· 252 if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) 253 return err; 254 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { 255 + if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) 256 + goto error_out; 257 + if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1)) 258 + goto error_out; 259 } 260 mpu->substream_output = substream; 261 set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); 262 return 0; 263 + 264 + error_out: 265 + if (mpu->open_output && mpu->close_output) 266 + mpu->close_output(mpu); 267 + return -EIO; 268 } 269 270 static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream) 271 { 272 struct snd_mpu401 *mpu; 273 + int err = 0; 274 275 mpu = substream->rmidi->private_data; 276 clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); 277 mpu->substream_input = NULL; 278 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) 279 + err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); 280 if (mpu->close_input) 281 mpu->close_input(mpu); 282 + if (err) 283 + return -EIO; 284 return 0; 285 } 286 287 static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) 288 { 289 struct snd_mpu401 *mpu; 290 + int err = 0; 291 292 mpu = substream->rmidi->private_data; 293 clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); 294 mpu->substream_output = NULL; 295 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) 296 + err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); 297 if (mpu->close_output) 298 mpu->close_output(mpu); 299 + if (err) 300 + return -EIO; 301 return 0; 302 } 303 ··· 316 snd_mpu401_uart_remove_timer(mpu, 1); 317 clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); 318 } 319 + 320 } 321 322 /*