summaryrefslogtreecommitdiff
path: root/sound/usb/line6/driver.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-19 15:54:00 +0100
committerTakashi Iwai <tiwai@suse.de>2015-01-20 08:17:16 +0100
commit85a9339becf0af4d547ceb6bb16d1893b05fbce4 (patch)
tree0f25a3def6f9aeca37f942c4aa70b88772a48259 /sound/usb/line6/driver.c
parent84ac9bb12e8158e1affad4ae7718eb653fa5e36d (diff)
ALSA: line6: Reorganize card resource handling
This is a fairly big rewrite regarding the card resource management in line6 drivers: - The card creation is moved into line6_probe(). This adds the global destructor to private_free, so that each driver doesn't have to call it any longer. - The USB disconnect callback handles the card release, thus each driver needs to concentrate on only its own resources. No need to snd_card_*() call in the destructor. - Fix the potential stall in disconnection by removing snd_card_free(). It's replaced with snd_card_free_when_closed() for asynchronous release. - The only remaining operation for the card in each driver is the call of snd_card_register(). All the rest are dealt in the common module by itself. - These ended up with removal of audio.[ch] as a result of a reduction of one layer. Each driver just needs to call line6_probe(). Tested-by: Chris Rorvick <chris@rorvick.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/line6/driver.c')
-rw-r--r--sound/usb/line6/driver.c82
1 files changed, 49 insertions, 33 deletions
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index b8f5134dcec2..8b6a658a8a58 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -15,7 +15,9 @@
#include <linux/slab.h>
#include <linux/usb.h>
-#include "audio.h"
+#include <sound/core.h>
+#include <sound/initval.h>
+
#include "capture.h"
#include "driver.h"
#include "midi.h"
@@ -481,17 +483,16 @@ ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr,
EXPORT_SYMBOL_GPL(line6_nop_read);
/*
- Generic destructor.
+ Card destructor.
*/
-static void line6_destruct(struct usb_interface *interface)
+static void line6_destruct(struct snd_card *card)
{
- struct usb_line6 *line6;
+ struct usb_line6 *line6 = card->private_data;
+ struct usb_device *usbdev;
- if (interface == NULL)
- return;
- line6 = usb_get_intfdata(interface);
- if (line6 == NULL)
+ if (!line6)
return;
+ usbdev = line6->usbdev;
/* free buffer memory first: */
kfree(line6->buffer_message);
@@ -500,8 +501,11 @@ static void line6_destruct(struct usb_interface *interface)
/* then free URBs: */
usb_free_urb(line6->urb_listen);
- /* make sure the device isn't destructed twice: */
- usb_set_intfdata(interface, NULL);
+ /* free interface data: */
+ kfree(line6);
+
+ /* decrement reference counters: */
+ usb_put_dev(usbdev);
}
/*
@@ -513,6 +517,7 @@ int line6_probe(struct usb_interface *interface,
int (*private_init)(struct usb_interface *, struct usb_line6 *))
{
struct usb_device *usbdev;
+ struct snd_card *card;
int interface_number;
int ret;
@@ -569,8 +574,26 @@ int line6_probe(struct usb_interface *interface,
}
}
+ ret = snd_card_new(line6->ifcdev,
+ SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, 0, &card);
+ if (ret < 0)
+ goto err_put;
+
+ line6->card = card;
+ strcpy(card->id, line6->properties->id);
+ strcpy(card->driver, DRIVER_NAME);
+ strcpy(card->shortname, line6->properties->name);
+ sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name,
+ dev_name(line6->ifcdev));
+ card->private_data = line6;
+ card->private_free = line6_destruct;
+
usb_set_intfdata(interface, line6);
+ /* increment reference counters: */
+ usb_get_dev(usbdev);
+
if (properties->capabilities & LINE6_CAP_CONTROL) {
/* initialize USB buffers: */
line6->buffer_listen =
@@ -612,15 +635,11 @@ int line6_probe(struct usb_interface *interface,
dev_info(&interface->dev, "Line6 %s now attached\n",
line6->properties->name);
- /* increment reference counters: */
- usb_get_intf(interface);
- usb_get_dev(usbdev);
-
return 0;
-err_destruct:
- line6_destruct(interface);
-err_put:
+ err_destruct:
+ snd_card_free(card);
+ err_put:
return ret;
}
EXPORT_SYMBOL_GPL(line6_probe);
@@ -642,29 +661,26 @@ void line6_disconnect(struct usb_interface *interface)
interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
line6 = usb_get_intfdata(interface);
+ if (!line6)
+ return;
- if (line6 != NULL) {
- if (line6->urb_listen != NULL)
- line6_stop_listen(line6);
+ if (line6->urb_listen != NULL)
+ line6_stop_listen(line6);
- if (usbdev != line6->usbdev)
- dev_err(line6->ifcdev,
- "driver bug: inconsistent usb device\n");
+ if (usbdev != line6->usbdev)
+ dev_err(line6->ifcdev, "driver bug: inconsistent usb device\n");
+ snd_card_disconnect(line6->card);
+ if (line6->disconnect)
line6->disconnect(interface);
- dev_info(&interface->dev, "Line6 %s now disconnected\n",
- line6->properties->name);
- }
-
- line6_destruct(interface);
+ dev_info(&interface->dev, "Line6 %s now disconnected\n",
+ line6->properties->name);
- /* free interface data: */
- kfree(line6);
+ /* make sure the device isn't destructed twice: */
+ usb_set_intfdata(interface, NULL);
- /* decrement reference counters: */
- usb_put_intf(interface);
- usb_put_dev(usbdev);
+ snd_card_free_when_closed(line6->card);
}
EXPORT_SYMBOL_GPL(line6_disconnect);