Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2318

kernel-2.6.18-128.1.10.el5.src.rpm

From: Brian Maly <bmaly@redhat.com>
Subject: [RHEL5.1 patch] fix panic in hda_codec
Date: Sun, 12 Aug 2007 13:11:44 -0400
Bugzilla: 251854
Message-Id: <46BF3F50.6090408@redhat.com>
Changelog: [sound] fix panic in hda_codec


I dont have a BZ yet... bugzilla seems to be unresponsive at the moment. 
I will followup with a BZ when I have one.
This should be a stop ship issue. So far this issue has affected both 
Dell and HP systems, perhaps others.

The problem is that on certain hardware that uses the snd_hda_intel 
driver, there is a panic at boot that occurs in hda_codec. This issue is 
a regression introduced with the ALSA 1.0.14-rc3 update. This patch 
resolves this panic, and without this patch RHEL5.1 is not shippable on 
affected hardware.

Testing of this patch reveals the panic dissapears and all audio 
functionality on the affected hardware works fine now.

Brian


--- linux-2.6.18.noarch/sound/pci/hda/hda_local.h.orig	2007-08-12 00:55:40.000000000 -0400
+++ linux-2.6.18.noarch/sound/pci/hda/hda_local.h	2007-08-12 00:56:44.000000000 -0400
@@ -199,6 +199,7 @@ struct hda_bus_unsolicited {
 	unsigned int rp, wp;
 
 	/* workqueue */
+	struct workqueue_struct *workq;
 	struct work_struct work;
 	struct hda_bus *bus;
 };
--- linux-2.6.18.noarch/sound/pci/hda/hda_codec.c.orig	2007-08-12 00:05:46.000000000 -0400
+++ linux-2.6.18.noarch/sound/pci/hda/hda_codec.c	2007-08-12 00:07:49.000000000 -0400
@@ -264,7 +264,7 @@ int snd_hda_queue_unsol_event(struct hda
 	unsol->queue[wp] = res;
 	unsol->queue[wp + 1] = res_ex;
 
-	schedule_work(&unsol->work);
+	queue_work(unsol->workq, &unsol->work);
 
 	return 0;
 }
@@ -274,11 +274,10 @@ EXPORT_SYMBOL(snd_hda_queue_unsol_event)
 /*
  * process queueud unsolicited events
  */
-static void process_unsol_events(struct work_struct *work)
+static void process_unsol_events(void *data)
 {
-	struct hda_bus_unsolicited *unsol =
-		container_of(work, struct hda_bus_unsolicited, work);
-	struct hda_bus *bus = unsol->bus;
+	struct hda_bus *bus = data;
+	struct hda_bus_unsolicited *unsol = bus->unsol;
 	struct hda_codec *codec;
 	unsigned int rp, caddr, res;
 
@@ -311,8 +310,13 @@ static int init_unsol_queue(struct hda_b
 		snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
 		return -ENOMEM;
 	}
-	INIT_WORK(&unsol->work, process_unsol_events, &unsol);
-	unsol->bus = bus;
+	unsol->workq = create_singlethread_workqueue("hda_codec");
+	if (! unsol->workq) {
+		snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
+		kfree(unsol);
+		return -ENOMEM;
+	}
+	INIT_WORK(&unsol->work, process_unsol_events, bus);
 	bus->unsol = unsol;
 	return 0;
 }
@@ -329,7 +333,7 @@ static int snd_hda_bus_free(struct hda_b
 	if (! bus)
 		return 0;
 	if (bus->unsol) {
-		flush_scheduled_work();
+		destroy_workqueue(bus->unsol->workq);
 		kfree(bus->unsol);
 	}
 	list_for_each_safe(p, n, &bus->codec_list) {