[ALSA] snd-ak4114: Fix two array overflows
[deliverable/linux.git] / sound / i2c / other / ak4114.c
index d351b3aa1916f3747b617df5270afeb108d1b60c..adbfd5884d0606cfce7547fc2757681ab2df746b 100644 (file)
@@ -35,24 +35,24 @@ MODULE_LICENSE("GPL");
 
 #define AK4114_ADDR                    0x00 /* fixed address */
 
-static void ak4114_stats(void *);
+static void ak4114_stats(struct work_struct *work);
 
-static void reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char val)
+static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val)
 {
        ak4114->write(ak4114->private_data, reg, val);
        if (reg <= AK4114_REG_INT1_MASK)
                ak4114->regmap[reg] = val;
-       else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4)
-               ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val;
+       else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
+               ak4114->txcsb[reg-AK4114_REG_TXCSB0] = val;
 }
 
-static inline unsigned char reg_read(ak4114_t *ak4114, unsigned char reg)
+static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg)
 {
        return ak4114->read(ak4114->private_data, reg);
 }
 
 #if 0
-static void reg_dump(ak4114_t *ak4114)
+static void reg_dump(struct ak4114 *ak4114)
 {
        int i;
 
@@ -62,33 +62,31 @@ static void reg_dump(ak4114_t *ak4114)
 }
 #endif
 
-static void snd_ak4114_free(ak4114_t *chip)
+static void snd_ak4114_free(struct ak4114 *chip)
 {
        chip->init = 1; /* don't schedule new work */
        mb();
-       if (chip->workqueue != NULL) {
-               flush_workqueue(chip->workqueue);
-               destroy_workqueue(chip->workqueue);
-       }
+       cancel_delayed_work(&chip->work);
+       flush_scheduled_work();
        kfree(chip);
 }
 
-static int snd_ak4114_dev_free(snd_device_t *device)
+static int snd_ak4114_dev_free(struct snd_device *device)
 {
-       ak4114_t *chip = device->device_data;
+       struct ak4114 *chip = device->device_data;
        snd_ak4114_free(chip);
        return 0;
 }
 
-int snd_ak4114_create(snd_card_t *card,
+int snd_ak4114_create(struct snd_card *card,
                      ak4114_read_t *read, ak4114_write_t *write,
-                     unsigned char pgm[7], unsigned char txcsb[5],
-                     void *private_data, ak4114_t **r_ak4114)
+                     const unsigned char pgm[7], const unsigned char txcsb[5],
+                     void *private_data, struct ak4114 **r_ak4114)
 {
-       ak4114_t *chip;
+       struct ak4114 *chip;
        int err = 0;
        unsigned char reg;
-       static snd_device_ops_t ops = {
+       static struct snd_device_ops ops = {
                .dev_free =     snd_ak4114_dev_free,
        };
 
@@ -100,18 +98,13 @@ int snd_ak4114_create(snd_card_t *card,
        chip->read = read;
        chip->write = write;
        chip->private_data = private_data;
+       INIT_DELAYED_WORK(&chip->work, ak4114_stats);
 
        for (reg = 0; reg < 7; reg++)
                chip->regmap[reg] = pgm[reg];
        for (reg = 0; reg < 5; reg++)
                chip->txcsb[reg] = txcsb[reg];
 
-       chip->workqueue = create_workqueue("snd-ak4114");
-       if (chip->workqueue == NULL) {
-               kfree(chip);
-               return -ENOMEM;
-       }
-
        snd_ak4114_reinit(chip);
 
        chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
@@ -129,21 +122,22 @@ int snd_ak4114_create(snd_card_t *card,
        return err < 0 ? err : -EIO;
 }
 
-void snd_ak4114_reg_write(ak4114_t *chip, unsigned char reg, unsigned char mask, unsigned char val)
+void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val)
 {
        if (reg <= AK4114_REG_INT1_MASK)
                reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
        else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
-               reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val);
+               reg_write(chip, reg,
+                         (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val);
 }
 
-void snd_ak4114_reinit(ak4114_t *chip)
+void snd_ak4114_reinit(struct ak4114 *chip)
 {
        unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg;
 
        chip->init = 1;
        mb();
-       flush_workqueue(chip->workqueue);
+       flush_scheduled_work();
        /* bring the chip to reset state and powerdown state */
        reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
        udelay(200);
@@ -158,8 +152,7 @@ void snd_ak4114_reinit(ak4114_t *chip)
        reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
        /* bring up statistics / event queing */
        chip->init = 0;
-       INIT_WORK(&chip->work, ak4114_stats, chip);
-       queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
+       schedule_delayed_work(&chip->work, HZ / 10);
 }
 
 static unsigned int external_rate(unsigned char rcs1)
@@ -176,8 +169,8 @@ static unsigned int external_rate(unsigned char rcs1)
        }
 }
 
-static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol,
-                                   snd_ctl_elem_info_t *uinfo)
+static int snd_ak4114_in_error_info(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
@@ -186,10 +179,10 @@ static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol,
        return 0;
 }
 
-static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol,
-                                  snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        long *ptr;
 
        spin_lock_irq(&chip->lock);
@@ -200,8 +193,8 @@ static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol,
        return 0;
 }
 
-static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol,
-                                 snd_ctl_elem_info_t *uinfo)
+static int snd_ak4114_in_bit_info(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
        uinfo->count = 1;
@@ -210,10 +203,10 @@ static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol,
        return 0;
 }
 
-static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol,
-                                snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        unsigned char reg = kcontrol->private_value & 0xff;
        unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
        unsigned char inv = (kcontrol->private_value >> 31) & 1;
@@ -222,8 +215,8 @@ static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol,
        return 0;
 }
 
-static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol,
-                               snd_ctl_elem_info_t *uinfo)
+static int snd_ak4114_rate_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
@@ -232,26 +225,26 @@ static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol,
        return 0;
 }
 
-static int snd_ak4114_rate_get(snd_kcontrol_t *kcontrol,
-                              snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4114_rate_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
 
        ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4114_REG_RCS1));
        return 0;
 }
 
-static int snd_ak4114_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
        uinfo->count = 1;
        return 0;
 }
 
-static int snd_ak4114_spdif_get(snd_kcontrol_t * kcontrol,
-                               snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        unsigned i;
 
        for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++)
@@ -259,10 +252,10 @@ static int snd_ak4114_spdif_get(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol,
-                                        snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_playback_get(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        unsigned i;
 
        for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
@@ -270,10 +263,10 @@ static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol,
-                                        snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_playback_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        unsigned i;
 
        for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
@@ -281,21 +274,21 @@ static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_ak4114_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
        uinfo->count = 1;
        return 0;
 }
 
-static int snd_ak4114_spdif_mask_get(snd_kcontrol_t * kcontrol,
-                                     snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_mask_get(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
 {
        memset(ucontrol->value.iec958.status, 0xff, AK4114_REG_RXCSB_SIZE);
        return 0;
 }
 
-static int snd_ak4114_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->value.integer.min = 0;
@@ -304,10 +297,10 @@ static int snd_ak4114_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
        return 0;
 }
 
-static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol,
-                                snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_pget(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        unsigned short tmp;
 
        ucontrol->value.integer.value[0] = 0xf8f2;
@@ -319,17 +312,17 @@ static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-static int snd_ak4114_spdif_qinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
        uinfo->count = AK4114_REG_QSUB_SIZE;
        return 0;
 }
 
-static int snd_ak4114_spdif_qget(snd_kcontrol_t * kcontrol,
-                                snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_qget(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
 {
-       ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+       struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
        unsigned i;
 
        for (i = 0; i < AK4114_REG_QSUB_SIZE; i++)
@@ -338,14 +331,14 @@ static int snd_ak4114_spdif_qget(snd_kcontrol_t * kcontrol,
 }
 
 /* Don't forget to change AK4114_CONTROLS define!!! */
-static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
+static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         "IEC958 Parity Errors",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_in_error_info,
        .get =          snd_ak4114_in_error_get,
-       .private_value = offsetof(ak4114_t, parity_errors),
+       .private_value = offsetof(struct ak4114, parity_errors),
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -353,7 +346,7 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_in_error_info,
        .get =          snd_ak4114_in_error_get,
-       .private_value = offsetof(ak4114_t, v_bit_errors),
+       .private_value = offsetof(struct ak4114, v_bit_errors),
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -361,7 +354,7 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_in_error_info,
        .get =          snd_ak4114_in_error_get,
-       .private_value = offsetof(ak4114_t, ccrc_errors),
+       .private_value = offsetof(struct ak4114, ccrc_errors),
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -369,7 +362,7 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_in_error_info,
        .get =          snd_ak4114_in_error_get,
-       .private_value = offsetof(ak4114_t, qcrc_errors),
+       .private_value = offsetof(struct ak4114, qcrc_errors),
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -447,11 +440,11 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
 }
 };
 
-int snd_ak4114_build(ak4114_t *ak4114,
-                    snd_pcm_substream_t *ply_substream,
-                    snd_pcm_substream_t *cap_substream)
+int snd_ak4114_build(struct ak4114 *ak4114,
+                    struct snd_pcm_substream *ply_substream,
+                    struct snd_pcm_substream *cap_substream)
 {
-       snd_kcontrol_t *kctl;
+       struct snd_kcontrol *kctl;
        unsigned int idx;
        int err;
 
@@ -482,7 +475,7 @@ int snd_ak4114_build(ak4114_t *ak4114,
        return 0;
 }
 
-int snd_ak4114_external_rate(ak4114_t *ak4114)
+int snd_ak4114_external_rate(struct ak4114 *ak4114)
 {
        unsigned char rcs1;
 
@@ -490,9 +483,9 @@ int snd_ak4114_external_rate(ak4114_t *ak4114)
        return external_rate(rcs1);
 }
 
-int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
+int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
 {
-       snd_pcm_runtime_t *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
+       struct snd_pcm_runtime *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
        unsigned long _flags;
        int res = 0;
        unsigned char rcs0, rcs1;
@@ -561,14 +554,14 @@ int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
        return res;
 }
 
-static void ak4114_stats(void *data)
+static void ak4114_stats(struct work_struct *work)
 {
-       ak4114_t *chip = (ak4114_t *)data;
+       struct ak4114 *chip = container_of(work, struct ak4114, work.work);
 
        if (chip->init)
                return;
        snd_ak4114_check_rate_and_errors(chip, 0);
-       queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
+       schedule_delayed_work(&chip->work, HZ / 10);
 }
 
 EXPORT_SYMBOL(snd_ak4114_create);
This page took 0.050558 seconds and 5 git commands to generate.