ALSA: hda - Add reboot notifier

The current snd-hda-intel driver seems blocking the power-off on some
devices like eeepc. Although this is likely a BIOS problem, we can add
a workaround by disabling IRQ lines before power-off operation.
This patch adds the reboot notifier to achieve it.

The detailed problem description is found in bug#11889:
http://bugme.linux-foundation.org/show_bug.cgi?id=11889

Tested-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
Cc: stable@kernel.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+29
+29
sound/pci/hda/hda_intel.c
··· 45 45 #include <linux/slab.h> 46 46 #include <linux/pci.h> 47 47 #include <linux/mutex.h> 48 + #include <linux/reboot.h> 48 49 #include <sound/core.h> 49 50 #include <sound/initval.h> 50 51 #include "hda_codec.h" ··· 398 397 399 398 /* for pending irqs */ 400 399 struct work_struct irq_pending_work; 400 + 401 + /* reboot notifier (for mysterious hangup problem at power-down) */ 402 + struct notifier_block reboot_notifier; 401 403 }; 402 404 403 405 /* driver types */ ··· 1983 1979 1984 1980 1985 1981 /* 1982 + * reboot notifier for hang-up problem at power-down 1983 + */ 1984 + static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) 1985 + { 1986 + struct azx *chip = container_of(nb, struct azx, reboot_notifier); 1987 + azx_stop_chip(chip); 1988 + return NOTIFY_OK; 1989 + } 1990 + 1991 + static void azx_notifier_register(struct azx *chip) 1992 + { 1993 + chip->reboot_notifier.notifier_call = azx_halt; 1994 + register_reboot_notifier(&chip->reboot_notifier); 1995 + } 1996 + 1997 + static void azx_notifier_unregister(struct azx *chip) 1998 + { 1999 + if (chip->reboot_notifier.notifier_call) 2000 + unregister_reboot_notifier(&chip->reboot_notifier); 2001 + } 2002 + 2003 + /* 1986 2004 * destructor 1987 2005 */ 1988 2006 static int azx_free(struct azx *chip) 1989 2007 { 1990 2008 int i; 2009 + 2010 + azx_notifier_unregister(chip); 1991 2011 1992 2012 if (chip->initialized) { 1993 2013 azx_clear_irq_pending(chip); ··· 2376 2348 pci_set_drvdata(pci, card); 2377 2349 chip->running = 1; 2378 2350 power_down_all_codecs(chip); 2351 + azx_notifier_register(chip); 2379 2352 2380 2353 dev++; 2381 2354 return err;