ALSA: core: use precomputed table to check userspace control params
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Tue, 10 Mar 2015 13:13:30 +0000 (22:13 +0900)
committerTakashi Iwai <tiwai@suse.de>
Tue, 10 Mar 2015 14:27:57 +0000 (15:27 +0100)
The parameters can be decided in compile time.

This commit adds precomputed table to reduce calculating time.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/control.c

index 35324a8e83c867f126256f67b493b5320b9652c7..0b85cbc27e4d2eb9afa7531cdb15eb7851386171 100644 (file)
@@ -1161,6 +1161,23 @@ static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
 static int snd_ctl_elem_add(struct snd_ctl_file *file,
                            struct snd_ctl_elem_info *info, int replace)
 {
+       /* The capacity of struct snd_ctl_elem_value.value.*/
+       static const unsigned int value_sizes[] = {
+               [SNDRV_CTL_ELEM_TYPE_BOOLEAN]   = sizeof(long),
+               [SNDRV_CTL_ELEM_TYPE_INTEGER]   = sizeof(long),
+               [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
+               [SNDRV_CTL_ELEM_TYPE_BYTES]     = sizeof(unsigned char),
+               [SNDRV_CTL_ELEM_TYPE_IEC958]    = sizeof(struct snd_aes_iec958),
+               [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
+       };
+       static const unsigned int max_value_counts[] = {
+               [SNDRV_CTL_ELEM_TYPE_BOOLEAN]   = 128,
+               [SNDRV_CTL_ELEM_TYPE_INTEGER]   = 128,
+               [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
+               [SNDRV_CTL_ELEM_TYPE_BYTES]     = 512,
+               [SNDRV_CTL_ELEM_TYPE_IEC958]    = 1,
+               [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
+       };
        struct snd_card *card = file->card;
        struct snd_kcontrol kctl, *_kctl;
        unsigned int access;
@@ -1168,8 +1185,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
        struct user_element *ue;
        int idx, err;
 
-       if (info->count < 1)
-               return -EINVAL;
        access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
                (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
                                 SNDRV_CTL_ELEM_ACCESS_INACTIVE|
@@ -1201,37 +1216,18 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
                kctl.tlv.c = snd_ctl_elem_user_tlv;
                access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
        }
-       switch (info->type) {
-       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
-       case SNDRV_CTL_ELEM_TYPE_INTEGER:
-               private_size = sizeof(long);
-               if (info->count > 128)
-                       return -EINVAL;
-               break;
-       case SNDRV_CTL_ELEM_TYPE_INTEGER64:
-               private_size = sizeof(long long);
-               if (info->count > 64)
-                       return -EINVAL;
-               break;
-       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
-               private_size = sizeof(unsigned int);
-               if (info->count > 128 || info->value.enumerated.items == 0)
-                       return -EINVAL;
-               break;
-       case SNDRV_CTL_ELEM_TYPE_BYTES:
-               private_size = sizeof(unsigned char);
-               if (info->count > 512)
-                       return -EINVAL;
-               break;
-       case SNDRV_CTL_ELEM_TYPE_IEC958:
-               private_size = sizeof(struct snd_aes_iec958);
-               if (info->count != 1)
-                       return -EINVAL;
-               break;
-       default:
+
+       if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+           info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64)
                return -EINVAL;
-       }
-       private_size *= info->count;
+       if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
+           info->value.enumerated.items == 0)
+               return -EINVAL;
+       if (info->count < 1 ||
+           info->count > max_value_counts[info->type])
+               return -EINVAL;
+
+       private_size = value_sizes[info->type] * info->count;
        ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
        if (ue == NULL)
                return -ENOMEM;