Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85a9339b authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarChris Rorvick <chris@rorvick.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 84ac9bb1
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
snd-usb-line6-y := 		\
		audio.o		\
		capture.o	\
		driver.o	\
		midi.o		\

sound/usb/line6/audio.c

deleted100644 → 0
+0 −74
Original line number Diff line number Diff line
/*
 * Line6 Linux USB driver - 0.9.1beta
 *
 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License as
 *	published by the Free Software Foundation, version 2.
 *
 */

#include <sound/core.h>
#include <sound/initval.h>
#include <linux/export.h>

#include "driver.h"
#include "audio.h"

/*
	Initialize the Line6 USB audio system.
*/
int line6_init_audio(struct usb_line6 *line6)
{
	struct snd_card *card;
	int err;

	err = snd_card_new(line6->ifcdev,
			   SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
			   THIS_MODULE, 0, &card);
	if (err < 0)
		return err;

	line6->card = card;

	strcpy(card->id, line6->properties->id);
	strcpy(card->driver, DRIVER_NAME);
	strcpy(card->shortname, line6->properties->name);
	/* longname is 80 chars - see asound.h */
	sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name,
		dev_name(line6->ifcdev));
	return 0;
}
EXPORT_SYMBOL_GPL(line6_init_audio);

/*
	Register the Line6 USB audio system.
*/
int line6_register_audio(struct usb_line6 *line6)
{
	int err;

	err = snd_card_register(line6->card);
	if (err < 0)
		return err;

	return 0;
}
EXPORT_SYMBOL_GPL(line6_register_audio);

/*
	Cleanup the Line6 USB audio system.
*/
void line6_cleanup_audio(struct usb_line6 *line6)
{
	struct snd_card *card = line6->card;

	if (card == NULL)
		return;

	snd_card_disconnect(card);
	snd_card_free(card);
	line6->card = NULL;
}
EXPORT_SYMBOL_GPL(line6_cleanup_audio);

sound/usb/line6/audio.h

deleted100644 → 0
+0 −21
Original line number Diff line number Diff line
/*
 * Line6 Linux USB driver - 0.9.1beta
 *
 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License as
 *	published by the Free Software Foundation, version 2.
 *
 */

#ifndef AUDIO_H
#define AUDIO_H

#include "driver.h"

extern void line6_cleanup_audio(struct usb_line6 *);
extern int line6_init_audio(struct usb_line6 *);
extern int line6_register_audio(struct usb_line6 *);

#endif
+0 −1
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>

#include "audio.h"
#include "capture.h"
#include "driver.h"
#include "pcm.h"
+49 −33
Original line number Diff line number Diff line
@@ -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,14 +635,10 @@ 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);
	snd_card_free(card);
 err_put:
	return ret;
}
@@ -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 (usbdev != line6->usbdev)
			dev_err(line6->ifcdev,
				"driver bug: inconsistent usb device\n");
		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);

	/* 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);

Loading