> > @@ -3406,7 +3429,7 @@
> >     if(card == NULL)
> >     {
> >             printk(KERN_WARNING "maestro: out of memory\n");
> > -           return 0;
> > +           return -ENOMEM;
> 
> request_region is unbalanced in this return path.

Thanks! 

Fixed patch below.

Ciao, Marcus

Index: drivers/sound/maestro.c
===================================================================
RCS file: /build/mm/work/repository/linux-mm/drivers/sound/maestro.c,v
retrieving revision 1.7
diff -u -r1.7 maestro.c
--- drivers/sound/maestro.c     2001/05/18 08:06:38     1.7
+++ drivers/sound/maestro.c     2001/05/21 21:06:55
@@ -115,6 +115,10 @@
  *     themselves, but we'll see.  
  *     
  * History
+ *  v0.15 - May 21 2001 - Marcus Meissner <[EMAIL PROTECTED]>
+ *      Ported to Linux 2.4 PCI API. Some clean ups, global devs list
+ *      removed (now using pci device driver data).
+ *      PM needs to be polished still. Bumped version.
  *  (still kind of v0.14) May 13 2001 - Ben Pfaff <[EMAIL PROTECTED]>
  *      Add support for 978 docking and basic hardware volume control
  *  (still kind of v0.14) Nov 23 - Alan Cox <[EMAIL PROTECTED]>
@@ -206,28 +210,6 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-
- #define DECLARE_WAITQUEUE(QUEUE,INIT) struct wait_queue QUEUE = {INIT, NULL}
- #define wait_queue_head_t struct wait_queue *
- #define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->base_address[0] & 
PCI_BASE_ADDRESS_IO_MASK)
- #define SILLY_INIT_SEM(SEM) SEM=MUTEX;
- #define init_waitqueue_head init_waitqueue
- #define SILLY_MAKE_INIT(FUNC) __initfunc(FUNC)
- #define SILLY_OFFSET(VMA) ((VMA)->vm_offset)
-
-
-#else
-
- #define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->resource[0].start)
- #define SILLY_INIT_SEM(SEM) init_MUTEX(&SEM)
- #define SILLY_MAKE_INIT(FUNC) __init FUNC
- #define SILLY_OFFSET(VMA) ((VMA)->vm_pgoff)
-
-
-#endif
-
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/ioport.h>
@@ -251,6 +233,8 @@
 
 #include "maestro.h"
 
+static struct pci_driver maestro_pci_driver;
+
 /* --------------------------------------------------------------------- */
 
 #define M_DEBUG 1
@@ -271,8 +255,17 @@
        
 static int clocking=48000;
 
+MODULE_AUTHOR("Zach Brown <[EMAIL PROTECTED]>, Alan Cox <[EMAIL PROTECTED]>");
+MODULE_DESCRIPTION("ESS Maestro Driver");
+#ifdef M_DEBUG
+MODULE_PARM(debug,"i");
+#endif
+MODULE_PARM(dsps_order,"i");
+MODULE_PARM(use_pm,"i");
+MODULE_PARM(clocking, "i");
+
 /* --------------------------------------------------------------------- */
-#define DRIVER_VERSION "0.14"
+#define DRIVER_VERSION "0.15"
 
 #ifndef PCI_VENDOR_ESS
 #define PCI_VENDOR_ESS                 0x125D
@@ -354,6 +347,11 @@
        [ACPI_D3] = ACPI_NONE
 };
 
+static char version[] __devinitdata =
+KERN_INFO "maestro: version " DRIVER_VERSION " time " __TIME__ " " __DATE__ "\n";
+
+
+
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
 
@@ -522,8 +520,6 @@
 
 static void check_suspend(struct ess_card *card);
 
-static struct ess_card *devs = NULL;
-
 /* --------------------------------------------------------------------- */
 
 
@@ -2133,17 +2129,25 @@
 }
 
 /* --------------------------------------------------------------------- */
-
 static int ess_open_mixdev(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
-       struct ess_card *card = devs;
-
-       while (card && card->dev_mixer != minor)
-               card = card->next;
+       struct ess_card *card = NULL;
+       struct pci_dev *pdev;
+       struct pci_driver *drvr;
+
+       pci_for_each_dev(pdev) {
+               drvr = pci_dev_driver (pdev);
+               if (drvr == &maestro_pci_driver) {
+                       card = (struct ess_card*)pci_get_drvdata (pdev);
+                       if (!card)
+                               continue;
+                       if (card->dev_mixer == minor)
+                               break;
+               }
+       }
        if (!card)
                return -ENODEV;
-
        file->private_data = card;
        return 0;
 }
@@ -2505,7 +2509,7 @@
 #endif
                goto out;
        ret = -EINVAL;
-       if (SILLY_OFFSET(vma) != 0)
+       if (vma->vm_pgoff != 0)
                goto out;
        size = vma->vm_end - vma->vm_start;
        if (size > (PAGE_SIZE << db->buforder))
@@ -2969,33 +2973,40 @@
 ess_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
-       struct ess_card *c = devs;
-       struct ess_state *s = NULL, *sp;
-       int i;
+       struct ess_state *s = NULL;
        unsigned char fmtm = ~0, fmts = 0;
-
+       struct pci_dev *pdev;
        /*
         *      Scan the cards and find the channel. We only
         *      do this at open time so it is ok
         */
-        
-       while (c!=NULL)
-       {
-               for(i=0;i<NR_DSPS;i++)
-               {
-                       sp=&c->channels[i];
-                       if(sp->dev_audio < 0)
-                               continue;
-                       if((sp->dev_audio ^ minor) & ~0xf)
+
+       pci_for_each_dev(pdev) {
+               struct ess_card *c;
+               struct pci_driver *drvr;
+
+               drvr = pci_dev_driver (pdev);
+               if (drvr == &maestro_pci_driver) {
+                       int i;
+                       struct ess_state *sp;
+
+                       c = (struct ess_card*)pci_get_drvdata (pdev);
+                       if (!c)
                                continue;
-                       s=sp;
+                       for(i=0;i<NR_DSPS;i++)
+                       {
+                               sp=&c->channels[i];
+                               if(sp->dev_audio < 0)
+                                       continue;
+                               if((sp->dev_audio ^ minor) & ~0xf)
+                                       continue;
+                               s=sp;
+                       }
                }
-               c=c->next;
        }
-               
        if (!s)
                return -ENODEV;
-               
+
                VALIDATE_STATE(s);
        file->private_data = s;
        /* wait for device to become free */
@@ -3371,32 +3382,44 @@
 }
 
 static int __init
-maestro_install(struct pci_dev *pcidev, int card_type)
+maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid)
 {
+       int card_type = pdid->driver_data;
        u32 n;
        int iobase;
-       int i;
+       int i, ret;
        struct ess_card *card;
        struct ess_state *ess;
        struct pm_dev *pmdev;
        int num = 0;
 
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+       static int printed_version;
+       if (!printed_version++)
+               printk(version);
+#endif
+
        /* don't pick up weird modem maestros */
        if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
-               return 0;
+               return -ENODEV;
+
+
+       if ((ret=pci_enable_device(pcidev)))
+               return ret;
                        
-       iobase = SILLY_PCI_BASE_ADDRESS(pcidev); 
+       iobase = pci_resource_start(pcidev,0);
+       if (!iobase || !(pci_resource_flags(pcidev, 0 ) & IORESOURCE_IO))
+               return -ENODEV;
+
+       if(pcidev->irq == 0)
+               return -ENODEV;
 
        /* stake our claim on the iospace */
        if( request_region(iobase, 256, card_names[card_type]) == NULL )
        {
                printk(KERN_WARNING "maestro: can't allocate 256 bytes I/O at 
0x%4.4x\n", iobase);
-               return 0;
-       }
-
-       /* this was tripping up some machines */
-       if(pcidev->irq == 0) {
-               printk(KERN_WARNING "maestro: pci subsystem reports irq 0, this might 
not be correct.\n");
+               return -EBUSY;
        }
 
        /* just to be sure */
@@ -3406,7 +3429,8 @@
        if(card == NULL)
        {
                printk(KERN_WARNING "maestro: out of memory\n");
-               return 0;
+               release_region(iobase, 256);
+               return -ENOMEM;
        }
        
        memset(card, 0, sizeof(*card));
@@ -3417,18 +3441,12 @@
        if (pmdev)
                pmdev->data = card;
 
-       if (register_reboot_notifier(&maestro_nb)) {
-               printk(KERN_WARNING "maestro: reboot notifier registration failed; may 
not reboot properly.\n");
-       }
-
        card->iobase = iobase;
        card->card_type = card_type;
        card->irq = pcidev->irq;
-       card->next = devs;
        card->magic = ESS_CARD_MAGIC;
        spin_lock_init(&card->lock);
        init_waitqueue_head(&card->suspend_queue);
-       devs = card;
 
        card->dock_mute_vol = 50;
        
@@ -3444,7 +3462,7 @@
                init_waitqueue_head(&s->dma_dac.wait);
                init_waitqueue_head(&s->open_wait);
                spin_lock_init(&s->lock);
-               SILLY_INIT_SEM(s->open_sem);
+               init_MUTEX(&s->open_sem);
                s->magic = ESS_STATE_MAGIC;
                
                s->apu[0] = 6*i;
@@ -3472,19 +3490,6 @@
        
        ess = &card->channels[0];
 
-       if (pci_enable_device(pcidev)) {
-               printk (KERN_ERR "maestro: pci_enable_device() failed\n");
-               for (i = 0; i < NR_DSPS; i++) {
-                       struct ess_state *s = &card->channels[i];
-                       if (s->dev_audio != -1)
-                               unregister_sound_dsp(s->dev_audio);
-               }
-               release_region(card->iobase, 256);
-               unregister_reboot_notifier(&maestro_nb);
-               kfree(card);
-               return 0;
-       }
-
        /*
         *      Ok card ready. Begin setup proper
         */
@@ -3534,7 +3539,7 @@
                mixer_push_state(card);
        }
        
-       if(request_irq(card->irq, ess_interrupt, SA_SHIRQ, card_names[card_type], 
card))
+       if((ret=request_irq(card->irq, ess_interrupt, SA_SHIRQ, card_names[card_type], 
+card)))
        {
                printk(KERN_ERR "maestro: unable to allocate irq %d,\n", card->irq);
                unregister_sound_mixer(card->dev_mixer);
@@ -3547,26 +3552,61 @@
                release_region(card->iobase, 256);              
                unregister_reboot_notifier(&maestro_nb);
                kfree(card);
-               return 0;
+               return ret;
        }
+       pci_set_drvdata(pcidev,card);
        /* now go to sleep 'till something interesting happens */
        maestro_power(card,ACPI_D2);
 
        printk(KERN_INFO "maestro: %d channels configured.\n", num);
-       return 1; 
+       return 0; 
 }
 
-int __init init_maestro(void)
-{
-       struct pci_dev *pcidev = NULL;
-       int foundone = 0;
+static void maestro_remove(struct pci_dev *pcidev) {
+       struct ess_card *card = pci_get_drvdata(pcidev);
+       int i;
+       
+       /* XXX maybe should force stop bob, but should be all 
+               stopped by _release by now */
+       free_irq(card->irq, card);
+       unregister_sound_mixer(card->dev_mixer);
+       for(i=0;i<NR_DSPS;i++)
+       {
+               struct ess_state *ess = &card->channels[i];
+               if(ess->dev_audio != -1)
+                       unregister_sound_dsp(ess->dev_audio);
+       }
+       /* Goodbye, Mr. Bond. */
+       maestro_power(card,ACPI_D3);
+       release_region(card->iobase, 256);
+       kfree(card);
+       pci_set_drvdata(pcidev,NULL);
+}
+
+static struct pci_device_id maestro_pci_tbl[] __devinitdata = {
+       {PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+TYPE_MAESTRO2},
+       {PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+TYPE_MAESTRO2E},
+       {PCI_VENDOR_ESS_OLD, PCI_DEVICE_ID_ESS_ESS0100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+TYPE_MAESTRO},
+       {0,}
+};
+MODULE_DEVICE_TABLE(pci, maestro_pci_tbl);
 
-       if (!pci_present())   /* No PCI bus in this machine! */
-               return -ENODEV;
-       printk(KERN_INFO "maestro: version " DRIVER_VERSION " time " __TIME__ " " 
__DATE__ "\n");
+static struct pci_driver maestro_pci_driver = {
+       name:"maestro",
+       id_table:maestro_pci_tbl,
+       probe:maestro_probe,
+       remove:maestro_remove,
+};
 
-       pcidev = NULL;
+int __init init_maestro(void)
+{
+       pci_module_init(&maestro_pci_driver);
 
+       if (register_reboot_notifier(&maestro_nb))
+               printk(KERN_WARNING "maestro: reboot notifier registration failed; may 
+not reboot properly.\n");
+#ifdef MODULE
+       printk(version);
+#endif
        if (dsps_order < 0)   {
                dsps_order = 1;
                printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order);
@@ -3575,97 +3615,29 @@
                dsps_order = MAX_DSP_ORDER;
                printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order);
        }
-
-       /*
-        *      Find the ESS Maestro 2.
-        */
-
-       while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, 
pcidev))!=NULL ) {
-               if (maestro_install(pcidev, TYPE_MAESTRO2))
-                       foundone=1;
-       }
-
-       /*
-        *      Find the ESS Maestro 2E
-        */
-
-       while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, 
pcidev))!=NULL) {
-               if (maestro_install(pcidev, TYPE_MAESTRO2E))
-                       foundone=1;
-       }
-
-       /*
-        *      ESS Maestro 1
-        */
-
-       while((pcidev = pci_find_device(PCI_VENDOR_ESS_OLD, PCI_DEVICE_ID_ESS_ESS0100, 
pcidev))!=NULL) {
-               if (maestro_install(pcidev, TYPE_MAESTRO))
-                       foundone=1;
-       }
-       if( ! foundone ) {
-               printk("maestro: no devices found.\n");
-               return -ENODEV;
-       }
        return 0;
 }
 
-static void nuke_maestros(void)
-{
-       struct ess_card *card;
-
-       /* we do these unconditionally, which is probably wrong */
-       pm_unregister_all(maestro_pm_callback);
-       unregister_reboot_notifier(&maestro_nb);
-
-       while ((card = devs)) {
-               int i;
-               devs = devs->next;
-       
-               /* XXX maybe should force stop bob, but should be all 
-                       stopped by _release by now */
-               free_irq(card->irq, card);
-               unregister_sound_mixer(card->dev_mixer);
-               for(i=0;i<NR_DSPS;i++)
-               {
-                       struct ess_state *ess = &card->channels[i];
-                       if(ess->dev_audio != -1)
-                               unregister_sound_dsp(ess->dev_audio);
-               }
-               /* Goodbye, Mr. Bond. */
-               maestro_power(card,ACPI_D3);
-               release_region(card->iobase, 256);
-               kfree(card);
-       }
-       devs = NULL;
-}
-
 static int maestro_notifier(struct notifier_block *nb, unsigned long event, void *buf)
 {
        /* this notifier is called when the kernel is really shut down. */
        M_printk("maestro: shutting down\n");
-       nuke_maestros();
+       /* this will remove all card instances too */
+       pci_unregister_driver(&maestro_pci_driver);
+       /* XXX dunno about power management */
        return NOTIFY_OK;
 }
 
 /* --------------------------------------------------------------------- */
 
-#ifdef MODULE
-MODULE_AUTHOR("Zach Brown <[EMAIL PROTECTED]>, Alan Cox <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION("ESS Maestro Driver");
-#ifdef M_DEBUG
-MODULE_PARM(debug,"i");
-#endif
-MODULE_PARM(dsps_order,"i");
-MODULE_PARM(use_pm,"i");
-MODULE_PARM(clocking, "i");
 
-void cleanup_module(void) {
+void cleanup_maestro(void) {
        M_printk("maestro: unloading\n");
-       nuke_maestros();
+       pci_unregister_driver(&maestro_pci_driver);
+       pm_unregister_all(maestro_pm_callback);
+       unregister_reboot_notifier(&maestro_nb);
 }
 
-#endif
-
 /* --------------------------------------------------------------------- */
 
 void
@@ -3824,3 +3796,4 @@
 }
 
 module_init(init_maestro);
+module_exit(cleanup_maestro);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to