]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - sound/core/device.c
ALSA: Use priority list for managing device list
[karo-tx-linux.git] / sound / core / device.c
index 856bfdc79cee21a497763496dff6ad12e23fc8da..53291ff21a0921ea34538b115653217523cfb33c 100644 (file)
@@ -45,6 +45,7 @@ int snd_device_new(struct snd_card *card, enum snd_device_type type,
                   void *device_data, struct snd_device_ops *ops)
 {
        struct snd_device *dev;
+       struct list_head *p;
 
        if (snd_BUG_ON(!card || !device_data || !ops))
                return -ENXIO;
@@ -53,17 +54,36 @@ int snd_device_new(struct snd_card *card, enum snd_device_type type,
                dev_err(card->dev, "Cannot allocate device, type=%d\n", type);
                return -ENOMEM;
        }
+       INIT_LIST_HEAD(&dev->list);
        dev->card = card;
        dev->type = type;
        dev->state = SNDRV_DEV_BUILD;
        dev->device_data = device_data;
        dev->ops = ops;
-       list_add(&dev->list, &card->devices);   /* add to the head of list */
+
+       /* insert the entry in an incrementally sorted list */
+       list_for_each_prev(p, &card->devices) {
+               struct snd_device *pdev = list_entry(p, struct snd_device, list);
+               if ((unsigned int)pdev->type <= (unsigned int)type)
+                       break;
+       }
+
+       list_add(&dev->list, p);
        return 0;
 }
-
 EXPORT_SYMBOL(snd_device_new);
 
+static struct snd_device *look_for_dev(struct snd_card *card, void *device_data)
+{
+       struct snd_device *dev;
+
+       list_for_each_entry(dev, &card->devices, list)
+               if (dev->device_data == device_data)
+                       return dev;
+
+       return NULL;
+}
+
 /**
  * snd_device_free - release the device from the card
  * @card: the card instance
@@ -82,9 +102,8 @@ int snd_device_free(struct snd_card *card, void *device_data)
        
        if (snd_BUG_ON(!card || !device_data))
                return -ENXIO;
-       list_for_each_entry(dev, &card->devices, list) {
-               if (dev->device_data != device_data)
-                       continue;
+       dev = look_for_dev(card, device_data);
+       if (dev) {
                /* unlink */
                list_del(&dev->list);
                if (dev->state == SNDRV_DEV_REGISTERED &&
@@ -103,7 +122,6 @@ int snd_device_free(struct snd_card *card, void *device_data)
                device_data, __builtin_return_address(0));
        return -ENXIO;
 }
-
 EXPORT_SYMBOL(snd_device_free);
 
 /**
@@ -125,9 +143,8 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
 
        if (snd_BUG_ON(!card || !device_data))
                return -ENXIO;
-       list_for_each_entry(dev, &card->devices, list) {
-               if (dev->device_data != device_data)
-                       continue;
+       dev = look_for_dev(card, device_data);
+       if (dev) {
                if (dev->state == SNDRV_DEV_REGISTERED &&
                    dev->ops->dev_disconnect) {
                        if (dev->ops->dev_disconnect(dev))
@@ -162,9 +179,8 @@ int snd_device_register(struct snd_card *card, void *device_data)
 
        if (snd_BUG_ON(!card || !device_data))
                return -ENXIO;
-       list_for_each_entry(dev, &card->devices, list) {
-               if (dev->device_data != device_data)
-                       continue;
+       dev = look_for_dev(card, device_data);
+       if (dev) {
                if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
                        if ((err = dev->ops->dev_register(dev)) < 0)
                                return err;
@@ -177,7 +193,6 @@ int snd_device_register(struct snd_card *card, void *device_data)
        snd_BUG();
        return -ENXIO;
 }
-
 EXPORT_SYMBOL(snd_device_register);
 
 /*
@@ -212,7 +227,7 @@ int snd_device_disconnect_all(struct snd_card *card)
 
        if (snd_BUG_ON(!card))
                return -ENXIO;
-       list_for_each_entry(dev, &card->devices, list) {
+       list_for_each_entry_reverse(dev, &card->devices, list) {
                if (snd_device_disconnect(card, dev->device_data) < 0)
                        err = -ENXIO;
        }
@@ -223,24 +238,17 @@ int snd_device_disconnect_all(struct snd_card *card)
  * release all the devices on the card.
  * called from init.c
  */
-int snd_device_free_all(struct snd_card *card, enum snd_device_cmd cmd)
+int snd_device_free_all(struct snd_card *card)
 {
-       struct snd_device *dev;
-       int err;
-       unsigned int range_low, range_high, type;
+       struct snd_device *dev, *next;
+       int ret = 0;
 
        if (snd_BUG_ON(!card))
                return -ENXIO;
-       range_low = (unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
-       range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
-      __again:
-       list_for_each_entry(dev, &card->devices, list) {
-               type = (unsigned int)dev->type;
-               if (type >= range_low && type <= range_high) {
-                       if ((err = snd_device_free(card, dev->device_data)) < 0)
-                               return err;
-                       goto __again;
-               }
+       list_for_each_entry_safe_reverse(dev, next, &card->devices, list) {
+               int err = snd_device_free(card, dev->device_data);
+               if (err < 0)
+                       ret = err;
        }
-       return 0;
+       return ret;
 }