All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: dveatch@woh.rr.com
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: 0.9.7c, cs4236b and kernel oops
Date: Thu, 16 Oct 2003 13:40:17 +0200	[thread overview]
Message-ID: <s5h3cdtif6m.wl@alsa2.suse.de> (raw)
In-Reply-To: <s5h65ipig02.wl@alsa2.suse.de>

[-- Attachment #1: Type: text/plain, Size: 148 bytes --]

At Thu, 16 Oct 2003 13:22:37 +0200,
I wrote:
> 
> could you try the attached patch?

found one more potential bug.  use this one instead.


Takashi

[-- Attachment #2: pnp-fix2.dif --]
[-- Type: application/octet-stream, Size: 5884 bytes --]

Index: alsa-driver/support/pnp/pnp.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-driver/support/pnp/pnp.c,v
retrieving revision 1.11
diff -u -r1.11 pnp.c
--- alsa-driver/support/pnp/pnp.c	24 Sep 2003 15:59:31 -0000	1.11
+++ alsa-driver/support/pnp/pnp.c	16 Oct 2003 11:36:49 -0000
@@ -158,46 +158,51 @@
 int pnp_register_card_driver(struct pnp_card_driver * drv)
 {
 	unsigned short vendor, device;
+	unsigned short subvendor, subdevice;
 	unsigned int i, res = 0;
 	const struct pnp_card_device_id *cid;
 	struct pnp_card *card;
 	struct pnp_dev *dev;
 	struct pnp_card_driver_instance *ninst = NULL;
 	
+	if (! drv->probe) {
+		printk(KERN_ERR "pnp: no probe function!\n");
+		return -EINVAL;
+	}
+
 	for (cid = drv->id_table; cid->id[0] != '\0'; cid++) {
-	      __next_card:
-		card = NULL;
-		do {
-		      __next:
-			if (parse_id(cid->id, &vendor, &device) < 0)
-				break;
-			card = (struct pnp_card *)isapnp_find_card(vendor, device, (struct isapnp_card *)card);
-			if (card) {
-				if (ninst == NULL) {
-					ninst = kmalloc(sizeof(*ninst), GFP_KERNEL);
-					if (ninst == NULL)
-						return res > 0 ? (int)res : -ENOMEM;
-					memset(ninst, 0, sizeof(*ninst));
-					INIT_LIST_HEAD(&ninst->list);
-				}
-				for (i = 0; i < PNP_MAX_DEVICES; i++)
-					ninst->devs[i] = NULL;
-				for (i = 0; i < PNP_MAX_DEVICES && cid->devs[i].id[0] != '\0'; i++) {
-					if (parse_id(cid->devs[i].id, &vendor, &device) < 0) {
-						cid++;
-						goto __next_card;
-					}
-					dev = ninst->devs[i] = (struct pnp_dev *)isapnp_find_dev((struct isapnp_card *)card, vendor, device, NULL);
-					if (dev == NULL)
-						goto __next;
-					if (! dev->p.active) {
-						if (! (drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
-							pnp_activate_dev(dev);
-						}
-					} else {
-						if ((drv->flags & PNP_DRIVER_RES_DISABLE) == PNP_DRIVER_RES_DISABLE) {
-							pnp_disable_dev(dev);
-						}
+		if (parse_id(cid->id, &vendor, &device) < 0)
+			continue;
+		card = NULL; 
+		while ((card = (struct pnp_card *)isapnp_find_card(vendor, device, (struct isapnp_card *)card)) != NULL) {
+			if (ninst == NULL) {
+				ninst = kmalloc(sizeof(*ninst), GFP_KERNEL);
+				if (ninst == NULL)
+					return res > 0 ? (int)res : -ENOMEM;
+				memset(ninst, 0, sizeof(*ninst));
+				INIT_LIST_HEAD(&ninst->list);
+			}
+			for (i = 0; i < PNP_MAX_DEVICES; i++)
+				ninst->devs[i] = NULL;
+			for (i = 0; i < PNP_MAX_DEVICES && cid->devs[i].id[0] != '\0'; i++) {
+				if (parse_id(cid->devs[i].id, &subvendor, &subdevice) < 0)
+					goto __next_card;
+				dev = ninst->devs[i] = (struct pnp_dev *)isapnp_find_dev((struct isapnp_card *)card, subvendor, subdevice, NULL);
+				if (dev == NULL)
+					break;
+			}
+			if (i == PNP_MAX_DEVICES || !cid->devs[i].id[0]) {
+				/* all parsed successfully */
+				/* activate or deactivate devices before probing */
+				for (i = 0; i < PNP_MAX_DEVICES; i++) {
+					dev = ninst->devs[i];
+					if (! dev)
+						break;
+					if ((drv->flags & PNP_DRIVER_RES_DISABLE) != PNP_DRIVER_RES_DISABLE)
+						dev->p.activate((struct isapnp_dev *)dev);
+					else {
+						dev->p.deactivate((struct isapnp_dev *)dev);
+						dev->p.prepare((struct isapnp_dev *)dev);
 					}
 				}
 				ninst->link.card = card;
@@ -209,7 +214,9 @@
 					res++;
 				}
 			}
-		} while (card != NULL);
+		}
+	__next_card:
+		;
 	}
 
 	if (ninst != NULL)
@@ -227,7 +234,8 @@
 		inst = list_entry(p, struct pnp_card_driver_instance, list);
 		if (inst->link.driver == drv) {
 			list_del(p);
-			drv->remove(&inst->link);
+			if (drv->remove)
+				drv->remove(&inst->link);
 			kfree(inst);
 		}
 	}
@@ -284,11 +292,14 @@
 
 static void copy_resource(struct resource *dst, const struct resource *src)
 {
-	dst->name = src->name;
-	dst->start = src->start;
-	dst->end = src->end;
-	dst->flags = (dst->flags & ~IORESOURCE_AUTO) |
-		(dst->flags & src->flags & IORESOURCE_AUTO);
+	/* copy if set manually */
+	if (src->name)
+		dst->name = src->name;
+	if (! (src->flags & IORESOURCE_AUTO)) {
+		dst->start = src->start;
+		dst->end = src->end;
+		dst->flags &= ~IORESOURCE_AUTO;
+	}
 }
 
 void pnp_init_resource_table(struct pnp_resource_table *table)
@@ -321,14 +332,9 @@
 	}
 }
 
-/* FIXME: this function cannot be called many times.  the setting is cleared at each time */
 int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode)
 {
 	unsigned int idx;
-	int err;
-
-	/* prepare the isapnp */
-	err = dev->p.prepare((struct isapnp_dev *)dev);
 
 	for (idx = 0; idx < PNP_MAX_IRQ; idx++)
 		copy_resource(&dev->p.irq_resource[idx], &res->irq_resource[idx]);
@@ -344,30 +350,8 @@
 
 int pnp_activate_dev(struct pnp_dev *dev)
 {
-	struct pnp_resource_table *tmp;
-	unsigned int idx;
-
 	if (dev->p.active)
-		return 0; /* FIXME: should be -EBUSY but 2.6 pnp layer behaves like this */
-
-	/* reserve the manual configuration */
-	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-	if (! tmp)
-		return -ENOMEM;
-	pnp_init_resource_table(tmp);
-	for (idx = 0; idx < PNP_MAX_IRQ; idx++)
-		copy_resource(&tmp->irq_resource[idx], &dev->p.irq_resource[idx]);
-	for (idx = 0; idx < PNP_MAX_DMA; idx++)
-		copy_resource(&tmp->dma_resource[idx], &dev->p.dma_resource[idx]);
-	for (idx = 0; idx < PNP_MAX_PORT; idx++)
-		copy_resource(&tmp->port_resource[idx], &dev->p.resource[idx]);
-	for (idx = 0; idx < PNP_MAX_MEM; idx++)
-		copy_resource(&tmp->mem_resource[idx], &dev->p.resource[idx+8]);
-
-	/* restore the manual configuration again */
-	pnp_manual_config_dev(dev, tmp, 0);
-	kfree(tmp);
-
+		return 0; /* 2.6 pnp layer behaves like this */
 	return dev->p.activate((struct isapnp_dev *)dev);
 }
 
@@ -376,7 +360,6 @@
 	if (! dev->p.active)
 		return 0;
 	return dev->p.deactivate((struct isapnp_dev *)dev);
-	/* FIXME: do we need clean up the resources again? */
 }
 
 static int __init pnp_init(void)

  reply	other threads:[~2003-10-16 11:40 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-15  1:24 0.9.7c, cs4236b and kernel oops Dennis Veatch
2003-10-15 10:33 ` Takashi Iwai
2003-10-15 13:20   ` Dennis Veatch
2003-10-15 14:21     ` Takashi Iwai
2003-10-16 11:22       ` Takashi Iwai
2003-10-16 11:40         ` Takashi Iwai [this message]
2003-10-16 12:46           ` Stumbles
2003-10-16 12:54             ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5h3cdtif6m.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=dveatch@woh.rr.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.