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