Commit f0d46320 authored by Alan Cox's avatar Alan Cox Committed by Steve French

[PATCH] bring es1371 in line with 2.4

Fixes security leak
Fixes a crash
Updates to use the new ac97
parent 52123103
...@@ -406,7 +406,7 @@ struct es1371_state { ...@@ -406,7 +406,7 @@ struct es1371_state {
struct proc_dir_entry *ps; struct proc_dir_entry *ps;
#endif /* ES1371_DEBUG */ #endif /* ES1371_DEBUG */
struct ac97_codec codec; struct ac97_codec *codec;
/* wave stuff */ /* wave stuff */
unsigned ctrl; unsigned ctrl;
...@@ -682,10 +682,10 @@ static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data) ...@@ -682,10 +682,10 @@ static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
unsigned long flags; unsigned long flags;
unsigned t, x; unsigned t, x;
spin_lock_irqsave(&s->lock, flags);
for (t = 0; t < POLL_COUNT; t++) for (t = 0; t < POLL_COUNT; t++)
if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))
break; break;
spin_lock_irqsave(&s->lock, flags);
/* save the current state for later */ /* save the current state for later */
x = wait_src_ready(s); x = wait_src_ready(s);
...@@ -724,11 +724,12 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr) ...@@ -724,11 +724,12 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
unsigned long flags; unsigned long flags;
unsigned t, x; unsigned t, x;
spin_lock_irqsave(&s->lock, flags);
/* wait for WIP to go away */ /* wait for WIP to go away */
for (t = 0; t < 0x1000; t++) for (t = 0; t < 0x1000; t++)
if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))
break; break;
spin_lock_irqsave(&s->lock, flags);
/* save the current state for later */ /* save the current state for later */
x = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)); x = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC));
...@@ -756,7 +757,6 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr) ...@@ -756,7 +757,6 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
/* restore SRC reg */ /* restore SRC reg */
wait_src_ready(s); wait_src_ready(s);
outl(x, s->io+ES1371_REG_SRCONV); outl(x, s->io+ES1371_REG_SRCONV);
spin_unlock_irqrestore(&s->lock, flags);
/* wait for WIP again */ /* wait for WIP again */
for (t = 0; t < 0x1000; t++) for (t = 0; t < 0x1000; t++)
...@@ -768,6 +768,7 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr) ...@@ -768,6 +768,7 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
if ((x = inl(s->io+ES1371_REG_CODEC)) & CODEC_RDY) if ((x = inl(s->io+ES1371_REG_CODEC)) & CODEC_RDY)
break; break;
spin_unlock_irqrestore(&s->lock, flags);
return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
} }
...@@ -1217,7 +1218,7 @@ static int es1371_open_mixdev(struct inode *inode, struct file *file) ...@@ -1217,7 +1218,7 @@ static int es1371_open_mixdev(struct inode *inode, struct file *file)
if (list == &devs) if (list == &devs)
return -ENODEV; return -ENODEV;
s = list_entry(list, struct es1371_state, devs); s = list_entry(list, struct es1371_state, devs);
if (s->codec.dev_mixer == minor) if (s->codec->dev_mixer == minor)
break; break;
} }
VALIDATE_STATE(s); VALIDATE_STATE(s);
...@@ -1236,7 +1237,7 @@ static int es1371_release_mixdev(struct inode *inode, struct file *file) ...@@ -1236,7 +1237,7 @@ static int es1371_release_mixdev(struct inode *inode, struct file *file)
static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{ {
struct es1371_state *s = (struct es1371_state *)file->private_data; struct es1371_state *s = (struct es1371_state *)file->private_data;
struct ac97_codec *codec = &s->codec; struct ac97_codec *codec = s->codec;
return mixdev_ioctl(codec, cmd, arg); return mixdev_ioctl(codec, cmd, arg);
} }
...@@ -1908,7 +1909,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -1908,7 +1909,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return -EINVAL; return -EINVAL;
} }
return mixdev_ioctl(&s->codec, cmd, arg); return mixdev_ioctl(s->codec, cmd, arg);
} }
static int es1371_open(struct inode *inode, struct file *file) static int es1371_open(struct inode *inode, struct file *file)
...@@ -2339,7 +2340,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int ...@@ -2339,7 +2340,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
return -EINVAL; return -EINVAL;
} }
return mixdev_ioctl(&s->codec, cmd, arg); return mixdev_ioctl(s->codec, cmd, arg);
} }
static int es1371_open_dac(struct inode *inode, struct file *file) static int es1371_open_dac(struct inode *inode, struct file *file)
...@@ -2661,12 +2662,8 @@ static int es1371_midi_release(struct inode *inode, struct file *file) ...@@ -2661,12 +2662,8 @@ static int es1371_midi_release(struct inode *inode, struct file *file)
break; break;
if (signal_pending(current)) if (signal_pending(current))
break; break;
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK)
remove_wait_queue(&s->midi.owait, &wait); break;
set_current_state(TASK_RUNNING);
unlock_kernel();
return -EBUSY;
}
tmo = (count * HZ) / 3100; tmo = (count * HZ) / 3100;
if (!schedule_timeout(tmo ? : 1) && tmo) if (!schedule_timeout(tmo ? : 1) && tmo)
printk(KERN_DEBUG PFX "midi timed out??\n"); printk(KERN_DEBUG PFX "midi timed out??\n");
...@@ -2720,7 +2717,7 @@ static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, in ...@@ -2720,7 +2717,7 @@ static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, in
/* print out CODEC state */ /* print out CODEC state */
len += sprintf (buf + len, "AC97 CODEC state\n"); len += sprintf (buf + len, "AC97 CODEC state\n");
for (cnt=0; cnt <= 0x7e; cnt = cnt +2) for (cnt=0; cnt <= 0x7e; cnt = cnt +2)
len+= sprintf (buf + len, "reg:0x%02x val:0x%04x\n", cnt, rdcodec(&s->codec, cnt)); len+= sprintf (buf + len, "reg:0x%02x val:0x%04x\n", cnt, rdcodec(s->codec, cnt));
if (fpos >=len){ if (fpos >=len){
*start = buf; *start = buf;
...@@ -2820,6 +2817,11 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2820,6 +2817,11 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
return -ENOMEM; return -ENOMEM;
} }
memset(s, 0, sizeof(struct es1371_state)); memset(s, 0, sizeof(struct es1371_state));
s->codec = ac97_alloc_codec();
if(s->codec == NULL)
goto err_codec;
init_waitqueue_head(&s->dma_adc.wait); init_waitqueue_head(&s->dma_adc.wait);
init_waitqueue_head(&s->dma_dac1.wait); init_waitqueue_head(&s->dma_dac1.wait);
init_waitqueue_head(&s->dma_dac2.wait); init_waitqueue_head(&s->dma_dac2.wait);
...@@ -2835,10 +2837,10 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2835,10 +2837,10 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
s->vendor = pcidev->vendor; s->vendor = pcidev->vendor;
s->device = pcidev->device; s->device = pcidev->device;
pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev); pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
s->codec.private_data = s; s->codec->private_data = s;
s->codec.id = 0; s->codec->id = 0;
s->codec.codec_read = rdcodec; s->codec->codec_read = rdcodec;
s->codec.codec_write = wrcodec; s->codec->codec_write = wrcodec;
printk(KERN_INFO PFX "found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n", printk(KERN_INFO PFX "found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
s->vendor, s->device, s->rev); s->vendor, s->device, s->rev);
if (!request_region(s->io, ES1371_EXTENT, "es1371")) { if (!request_region(s->io, ES1371_EXTENT, "es1371")) {
...@@ -2855,7 +2857,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2855,7 +2857,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
/* register devices */ /* register devices */
if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0) if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0)
goto err_dev1; goto err_dev1;
if ((res=(s->codec.dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1))) < 0) if ((res=(s->codec->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1))) < 0)
goto err_dev2; goto err_dev2;
if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1))) < 0) if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1))) < 0)
goto err_dev3; goto err_dev3;
...@@ -2938,7 +2940,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2938,7 +2940,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
/* init the sample rate converter */ /* init the sample rate converter */
src_init(s); src_init(s);
/* codec init */ /* codec init */
if (!ac97_probe_codec(&s->codec)) { if (!ac97_probe_codec(s->codec)) {
res = -ENODEV; res = -ENODEV;
goto err_gp; goto err_gp;
} }
...@@ -2947,16 +2949,16 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2947,16 +2949,16 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
fs = get_fs(); fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
val = SOUND_MASK_LINE; val = SOUND_MASK_LINE;
mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
val = initvol[i].vol; val = initvol[i].vol;
mixdev_ioctl(&s->codec, initvol[i].mixch, (unsigned long)&val); mixdev_ioctl(s->codec, initvol[i].mixch, (unsigned long)&val);
} }
/* mute master and PCM when in S/PDIF mode */ /* mute master and PCM when in S/PDIF mode */
if (s->spdif_volume != -1) { if (s->spdif_volume != -1) {
val = 0x0000; val = 0x0000;
s->codec.mixer_ioctl(&s->codec, SOUND_MIXER_WRITE_VOLUME, (unsigned long)&val); s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_VOLUME, (unsigned long)&val);
s->codec.mixer_ioctl(&s->codec, SOUND_MIXER_WRITE_PCM, (unsigned long)&val); s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_PCM, (unsigned long)&val);
} }
set_fs(fs); set_fs(fs);
/* turn on S/PDIF output driver if requested */ /* turn on S/PDIF output driver if requested */
...@@ -2984,7 +2986,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2984,7 +2986,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
err_dev4: err_dev4:
unregister_sound_dsp(s->dev_dac); unregister_sound_dsp(s->dev_dac);
err_dev3: err_dev3:
unregister_sound_mixer(s->codec.dev_mixer); unregister_sound_mixer(s->codec->dev_mixer);
err_dev2: err_dev2:
unregister_sound_dsp(s->dev_audio); unregister_sound_dsp(s->dev_audio);
err_dev1: err_dev1:
...@@ -2993,6 +2995,8 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic ...@@ -2993,6 +2995,8 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
err_irq: err_irq:
release_region(s->io, ES1371_EXTENT); release_region(s->io, ES1371_EXTENT);
err_region: err_region:
err_codec:
ac97_release_codec(s->codec);
kfree(s); kfree(s);
return res; return res;
} }
...@@ -3018,9 +3022,10 @@ static void __devinit es1371_remove(struct pci_dev *dev) ...@@ -3018,9 +3022,10 @@ static void __devinit es1371_remove(struct pci_dev *dev)
} }
release_region(s->io, ES1371_EXTENT); release_region(s->io, ES1371_EXTENT);
unregister_sound_dsp(s->dev_audio); unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->codec.dev_mixer); unregister_sound_mixer(s->codec->dev_mixer);
unregister_sound_dsp(s->dev_dac); unregister_sound_dsp(s->dev_dac);
unregister_sound_midi(s->dev_midi); unregister_sound_midi(s->dev_midi);
ac97_release_codec(s->codec);
kfree(s); kfree(s);
pci_set_drvdata(dev, NULL); pci_set_drvdata(dev, NULL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment