|
@@ -582,6 +582,33 @@ static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
|
|
|
urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
|
|
|
}
|
|
|
|
|
|
+static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < PCM_N_URBS; i++) {
|
|
|
+ rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
|
|
|
+ * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
|
|
|
+ if (!rt->out_urbs[i].buffer)
|
|
|
+ return -ENOMEM;
|
|
|
+ rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
|
|
|
+ * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
|
|
|
+ if (!rt->in_urbs[i].buffer)
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < PCM_N_URBS; i++) {
|
|
|
+ kfree(rt->out_urbs[i].buffer);
|
|
|
+ kfree(rt->in_urbs[i].buffer);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int usb6fire_pcm_init(struct sfire_chip *chip)
|
|
|
{
|
|
|
int i;
|
|
@@ -593,6 +620,13 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
|
|
|
if (!rt)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ ret = usb6fire_pcm_buffers_init(rt);
|
|
|
+ if (ret) {
|
|
|
+ usb6fire_pcm_buffers_destroy(rt);
|
|
|
+ kfree(rt);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
rt->chip = chip;
|
|
|
rt->stream_state = STREAM_DISABLED;
|
|
|
rt->rate = ARRAY_SIZE(rates);
|
|
@@ -614,6 +648,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
|
|
|
|
|
|
ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
|
|
|
if (ret < 0) {
|
|
|
+ usb6fire_pcm_buffers_destroy(rt);
|
|
|
kfree(rt);
|
|
|
snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
|
|
|
return ret;
|
|
@@ -625,6 +660,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
|
|
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
|
|
|
|
|
|
if (ret) {
|
|
|
+ usb6fire_pcm_buffers_destroy(rt);
|
|
|
kfree(rt);
|
|
|
snd_printk(KERN_ERR PREFIX
|
|
|
"error preallocating pcm buffers.\n");
|
|
@@ -669,6 +705,9 @@ void usb6fire_pcm_abort(struct sfire_chip *chip)
|
|
|
|
|
|
void usb6fire_pcm_destroy(struct sfire_chip *chip)
|
|
|
{
|
|
|
- kfree(chip->pcm);
|
|
|
+ struct pcm_runtime *rt = chip->pcm;
|
|
|
+
|
|
|
+ usb6fire_pcm_buffers_destroy(rt);
|
|
|
+ kfree(rt);
|
|
|
chip->pcm = NULL;
|
|
|
}
|