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 #include <linux/slab.h> 46 #include <linux/pci.h> 47 #include <linux/mutex.h> 48 #include <sound/core.h> 49 #include <sound/initval.h> 50 #include "hda_codec.h" ··· 398 399 /* for pending irqs */ 400 struct work_struct irq_pending_work; 401 }; 402 403 /* driver types */ ··· 1983 1984 1985 /* 1986 * destructor 1987 */ 1988 static int azx_free(struct azx *chip) 1989 { 1990 int i; 1991 1992 if (chip->initialized) { 1993 azx_clear_irq_pending(chip); ··· 2376 pci_set_drvdata(pci, card); 2377 chip->running = 1; 2378 power_down_all_codecs(chip); 2379 2380 dev++; 2381 return err;
··· 45 #include <linux/slab.h> 46 #include <linux/pci.h> 47 #include <linux/mutex.h> 48 + #include <linux/reboot.h> 49 #include <sound/core.h> 50 #include <sound/initval.h> 51 #include "hda_codec.h" ··· 397 398 /* for pending irqs */ 399 struct work_struct irq_pending_work; 400 + 401 + /* reboot notifier (for mysterious hangup problem at power-down) */ 402 + struct notifier_block reboot_notifier; 403 }; 404 405 /* driver types */ ··· 1979 1980 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 + /* 2004 * destructor 2005 */ 2006 static int azx_free(struct azx *chip) 2007 { 2008 int i; 2009 + 2010 + azx_notifier_unregister(chip); 2011 2012 if (chip->initialized) { 2013 azx_clear_irq_pending(chip); ··· 2348 pci_set_drvdata(pci, card); 2349 chip->running = 1; 2350 power_down_all_codecs(chip); 2351 + azx_notifier_register(chip); 2352 2353 dev++; 2354 return err;